1最大子数组和
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
void DP(int a[], int n) {
int dp[100];
int i, j, maxVal = INT_MIN;
memset(dp, 0 , sizeof(dp));
for(i = 1; i <= n ;i ++) {
dp[i]=max(dp[i-1]+a[i], a[i]);
if(maxVal < dp[i])
maxVal = dp[i];
}
cout<<maxVal<<endl;
}
int main() {
int n, a[100];
cin>>n;
for(int i = 1; i<=n; i++) {
cin >>a[i];
}
DP(a,n);
system("pause");
}
2求最长的不上升子序列长度
设dp[i]表示前i个数的最长不上升序列的长度。
则,dp[i]=max{dp[j]+1},其中j<i and a[j]>=a[i]
这里0<j<i<=n。
#include <iostream>
#include <cstdio>
using namespace std;
void DP(int a[], int begin, int end) {
int i, j, maxVal, dp[100];
memset(dp, 0 , sizeof(dp));
for(i = begin;i <=end; i++) {
maxVal = INT_MIN;
dp[i] = 1;
for(j=begin; j <i;j++) {
if(a[i]<= a[j])
if(dp[j] > maxVal)
maxVal = dp[j];
dp[i] = maxVal +1;
}
}
//for(i= begin; i<=end;i++)
// cout<<dp[i]<<" ";
//cout<<endl;
cout<<dp[end]<<endl;
}
int main() {
int n, i;
int a[100];
cin>>n;
for(i =1; i<= n;i++)
cin>>a[i];
DP(a,1,n);
system("pause");
}
3.最长回文子序列
并不是指子串。比如CCCAC 最长回文子 序列为 CCCC 而不是CCC
从二维数组dp右下角开始构造。 加入a[i]=a[j];那么问题就转为他的子串 ,即dp[i][j] = dp[i+1][j-1]+2
void DP(char a[], int begin, int end) {
int dp[100][100];
int i,j;
memset(dp, 0 ,sizeof(dp));
for(j = end;j >=begin ;j--) dp[j][j] =1;
for(i = end-1;i >=begin ;i--){
for(j = i+1; j <=end; j++) {
if(a[i] == a[j])
dp[i][j] = dp[i+1][j-1] +2;
else
dp[i][j] = dp[i][j-1];
}
}
for(i=begin;i<=end;i++){
for(j=begin;j<=end;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
cout<<endl;
cout<<dp[begin][end]<<endl;
}
int main() {
int n, i;
char a[100];
cin>>n;
for(i =1; i<= n;i++)
cin>>a[i];
DP(a,1,n);
system("pause");
}
在一个数组中,检测是否存和等于某个数的子序列
比如n个数 ,a1, a2,a3.....an; 存在一个子序列a1, ak ,am.. (k<m)之和等于常数K
01背包的变形,其实也就是看数组里的数是否能填满容量为K的背包
#include <iostream>
#include <cstdio>
using namespace std;
void DP(int a[], int begin, int end, int t) {
int i,j;
int dp[100][100];
memset(dp,0,sizeof(dp));
for(i= begin;i<=end;i++) {//前i物品
for(j=1;j<=t;j++){ //背包容量
if(j>=a[i])
dp[i][j] = max(dp[i-1][j-a[i]]+a[i], dp[i-1][j]);
else
dp[i][j] = dp[i-1][j];
}
}
//for(i=begin;i<=end;i++)
//{
// for(j=1;j<=t;j++)
// cout<<dp[i][j]<<" ";
// cout<<endl;
//}
if(dp[end][t]==t)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
int main() {
int n, i, t;
int a[100];
cin>>n>>t;
for(i =1; i<= n;i++)
cin>>a[i];
DP(a,1,n,t);
system("pause");
}
酒店建造:n个可选的地址位于一条直线上,他们距离起点的距离依次为m1,m2...mn
在每个选址上最多修一座酒店,在位置i修建带来的利润为pi;
两个酒店之间的距离至少间隔k里
void DP(int a[],int p[], int begin, int end, int k) {
int dp[100];
int i,j;
int MAX = INT_MIN;
memset(dp, 0, sizeof(dp));
dp[1] = p[1];
for(i= begin; i<=end; i++) {
for(j=i-1; j>=begin; j--) {
if(a[i]-a[j] >= k){
dp[i] = dp[j]+p[i];
if(dp[i] > MAX)
MAX=dp[i];
break;
}
}
}
cout<<MAX<<endl;
}
int main() {
int n, i, k;
int a[100], p[100];
cin>>n>>k;
for(i =1; i<= n;i++)
cin>>a[i]>>p[i];
DP(a,p,1,n,k);
system("pause");
}
凑硬币
给定数量无限的硬币面值分别为x1,x2,x3...xn;将价格v兑换成零钱,能否满足
void DP(int a[],int begin, int end, int k) {
int dp[100][100];
int n,v,j;
memset(dp, 0, sizeof(dp));
for(n=begin;n<=end;n++) {
for(v=1;v<=k;v++){
for(j=0;j*a[n]<=v;j++) {
dp[n][v] = max(dp[n-1][v-j*a[n]]+j*a[n] ,dp[n-1][v-j*a[n]]);
}
}
}
//for(int i=begin;i<=end;i++){
// for(j=0;j<=k;j++)
// cout<<dp[i][j]<<" ";
// cout<<endl;
//}
//cout<<dp[end][k]<<endl;
if(dp[end][k] == k)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
int main() {
int n, i, k;
int a[100], p[100];
cin>>n>>k;
for(i =1; i<= n;i++)
cin>>a[i];
DP(a,1,n,k);
system("pause");
}