动态规划问题总结
最大子列和问题
int main(){ int n; scanf("%d",&n); int dp[maxn]; fill(dp,dp+maxn,0); int list[maxn]; for(int i=1;i<=n;i++){ scanf("%d",&list[i]); } for(int i=1;i<=n;i++){ dp[i]=max(dp[i],dp[i-1]+list[i]); } int maxval=0; for(int i=1;i<=n;i++){ if(dp[i]>maxval){ maxval=dp[i]; } } printf("%d",maxval); }
>> 6
>> -2 11 -4 13 -5 -2
<< 20
最大不下降子序列 LIS
用一个pre数组来进行回溯,如果结果不唯一,可以用一个vector<int> pre[maxn] 来记录,然后DFS
int main(){ int n; scanf("%d",&n); int pre[maxn];fill(pre,pre+maxn,-1); int dp[maxn]; fill(dp,dp+maxn,0); int choice[maxn][maxn]; fill(choice[0],choice[0]+maxn*maxn,0); int list[maxn]; for(int i=1;i<=n;i++){ scanf("%d",&list[i]); } for(int i=1;i<=n;i++){ dp[i]=1; for(int j=1;j<i;j++){ if(list[j]<=list[i]&&dp[i]<=dp[j]+1){ dp[i]=dp[j]+1; pre[i]=j; // 用于回溯 } } } int maxval=0, maxid; for(int i=1;i<=n;i++){ if(dp[i]>=maxval){ maxval=dp[i]; maxid=i; } } printf("%d\n",maxval); int ptr=maxid; while(ptr!=-1){ printf("%d ",list[ptr]); ptr=pre[ptr]; } }
>> 8
>> 1 2 3 -9 3 9 0 11
<< 6
<< 11 9 3 3 2 1
最长回文子串
int main(){ int choice[maxn][maxn]; fill(choice[0],choice[0]+maxn*maxn,0); string s="patzjujztaccbcc"; int n = s.length(); int dp[maxn][maxn]; fill(dp[0],dp[0]+maxn*maxn,0); for(int i=0;i<n;i++){ dp[i][i]=1; choice[i][i]=1; if(i!=n&&s[i]==s[i+1]){ dp[i][i+1]=1; choice[i][i+1]=1; } } int ans; vector<nodetype> ansSet; for(int L=3;L<=n;L++){ nodetype node; ansSet.clear(); for(int i=0;i+L-1<n;i++){ int j=i+L-1; if(s[i]==s[j]&&dp[i+1][j-1]){ dp[i][j]=L; choice[i][j]=1; node.x=i; node.y=j; ansSet.push_back(node); ans=L; } } } printf("%d\n%d %d\n",ans,ansSet[0].x,ansSet[0].y); for(int i=ansSet[0].x;i<=ansSet[0].y;i++){ printf("%c",s[i]); } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ printf("%d ",dp[i][j]); } printf("\n"); } }
回文长度 9 1 9 回文 atzjujzta dp矩阵 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 1 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 1 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 1 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 5 0 0 0 0 0 0 0 0 0 0 0 1 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
01背包问题
W重量: 3 5 1 2 2
C价值 :4 5 2 1 3
有一个容量为8的包怎么装价值最大:
一种写法
for(int i=1;i<=n;i++){ for(int j=w[i];j<=v;j++){ dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+c[i]); } }
}
为了减少空间复杂度,可以每次都社区前面的行,那么就有下面的滚动数组写法
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 #include <map> 5 #include <cmath> 6 #include <stack> 7 #include <string> 8 using namespace std; 9 const int maxn = 105; 10 const int maxv = 105; 11 12 bool cmp(int a,int b){ 13 return a>b; 14 } 15 16 int main(){ 17 int n,v; 18 int dp[maxn]; 19 int choice[maxn][maxv]; 20 int w[maxn],c[maxn]; 21 scanf("%d %d",&n,&v); 22 for(int i=1;i<=n;i++){ 23 scanf("%d",&w[i]); 24 } 25 for(int i=1;i<=n;i++){ 26 scanf("%d",&c[i]); 27 } 28 //sort() 29 fill(choice[0],choice[0]+maxn*maxv,0); 30 fill(dp,dp+maxn,0); 31 for(int i=1;i<=n;i++){ 32 for(int j=v;j-w[i]>=0;j--){ 33 if(dp[j]<dp[j-w[i]]+c[i]){ 34 dp[j]=dp[j-w[i]]+c[i]; 35 choice[i][j]=1; 36 } 37 } 38 } 39 printf("%d",dp[v]); 40 /*int i=n, j=v; 41 while(j>0){ 42 if(choice[i][j]){ 43 printf("%d ",) 44 } 45 }*/ 46 } 47 /* 48 5 8 49 3 5 1 2 2 50 4 5 2 1 3 51 */
i的每次迭代结果
# 0 0 0 4 4 4 4 4 4 # 0 0 0 4 4 5 5 5 9 # 0 2 2 4 6 6 7 7 9 # 0 2 2 4 6 6 7 7 9 # 0 2 3 5 6 7 9 9 10
完全背包问题
每一个物品可以用无数次
for(int i=1;i<=n;i++){ for(int j=w[i];j<=v;j++){ dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+c[i]); } }
posted on 2018-12-06 19:40 iojafekniewg 阅读(286) 评论(0) 编辑 收藏 举报