LoKwongho

mm

动态规划问题总结

最大子列和问题

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  阅读(284)  评论(0编辑  收藏  举报

导航

My Email guangho2743##foxmail.com : )