zoukankan      html  css  js  c++  java
  • 动态规划问题总结

    最大子列和问题

    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]);
            }
        }

  • 相关阅读:
    1442. Count Triplets That Can Form Two Arrays of Equal XOR
    1441. Build an Array With Stack Operations
    312. Burst Balloons
    367. Valid Perfect Square
    307. Range Sum Query
    1232. Check If It Is a Straight Line
    993. Cousins in Binary Tree
    1436. Destination City
    476. Number Complement
    383. Ransom Note
  • 原文地址:https://www.cnblogs.com/lokwongho/p/10076548.html
Copyright © 2011-2022 走看看