• 动态规划问题总结


    最大子列和问题

    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
    ",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
    %d %d
    ",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("
    ");
        }
    }
    

    回文长度 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]);
            }
        }

  • 相关阅读:
    setlocale set the current locale
    测试一个目录下的文件共有多少行
    ping中用到的校验和算法
    atomic integer operations P176
    我要理解1为什么是0xffffffff,所以写了下面的程序理解。
    贝叶斯网络中一个节点的类
    bash 的浮点除法
    shell(1)
    AndroidBroadcast详解与汇总
    AndroidActivity详解与汇总
  • 原文地址:https://www.cnblogs.com/lokwongho/p/10076548.html
Copyright © 2020-2023  润新知