• DP训练


    1. HDU 1003 最大和连续子序列

    状态方程:dp[i]=max(dp[j-1]+num[i],num[i]);

    解:存放dp数组每个元素都是从左至右最大连续子序列的值,即dp[i]为从0~i处最大连续子序列的值

    注意边界

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string.h>
     4 using namespace std;
     5 #define N 100005
     6 int dp[N];
     7 int a[N];
     8 int main()
     9 {
    10     int t;
    11     while(scanf("%d",&t)!=EOF)
    12     {
    13         int c=1,T=t;
    14         while(t--)
    15         {
    16             memset(dp,0,N);
    17             int n;
    18             scanf("%d",&n);
    19             for(int i=1; i<=n; i++)
    20             {
    21                 scanf("%d",&a[i]);
    22             }
    23             dp[1]=a[1];
    24             for(int j=2; j<=n; j++)
    25             {
    26                  dp[j]=max(dp[j-1]+a[j],a[j]);
    27             }
    28 
    29             int mx=-999999999;
    30             int st=0,en=0;
    31             for(int i=1; i<=n; i++)
    32                 if(mx<dp[i])
    33                 {
    34                     mx=dp[i];
    35                     en=i;
    36                 }
    37             st=en;
    38             int sum=0;
    39             for(int i=en; i>=1; i--)
    40             {
    41                 sum+=a[i];
    42                 if(sum==mx)
    43                 {
    44                     st=i;
    45                 }
    46             }
    47             printf("Case %d:
    %d %d %d
    ",c,mx,st,en);
    48             if(c!=T)printf("
    ");
    49             c+=1;
    50         }
    51     }
    52     return 0;
    53 }
    View Code

    2. HDU 1087 最大和连续递增子序列

    状态方程:v[i]=max(v[i],v[j]+num[i]);//v[j]存放的为最优的递增和加上当前的

    解:存放dp数组的每个元素都是从左至右最大和递增子序列的值,即dp[i]为0~i处最优最大和递增子序列的值

    例如:五个数 :5 1 2 4 6

    扫描到6时,从第一开始向后扫描,5<6  v[0]=5,num[i]=6,此时v[i]=11,

                     1<6  v[1]=1,~~                   v[i]=11

                     2<6  v[2]=3~~                    v[i]=11

                    4<6 v[3]=7 ~~                  v[i]=13

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 int num[N];
     5 int v[N];
     6 int main()
     7 {
     8     int n;
     9     while(scanf("%d",&n)!=EOF&&n)
    10     {
    11         memset(v,0,sizeof(v));
    12         for(int i=1; i<=n; i++)
    13             scanf("%d",&num[i]);
    14 
    15         for(int i=1; i<=n; i++)
    16         {
    17             for(int j=1; j<i; j++)
    18             {
    19                 if(num[i]>num[j])
    20                     v[i]=max(v[i],v[j]+num[i]);
    21             }
    22             v[i]=max(v[i],num[i]);
    23         }
    24         int mx=-999999;
    25         for(int i=1; i<=n; i++)
    26         {
    27             mx=max(mx,v[i]);
    28         }
    29         printf("%d
    ",mx);
    30     }
    31     return 0;
    32 }
    View Code

    3. 马拦卒过河(动态规划思维)

    解:每个位置为上一个与左一个路径之和

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 16
     4 int dp[N][N];
     5 
     6 void mControl(int x,int y)
     7 {
     8     int xx[8]= {x-2,x-2,x-1,x-1,x+1,x+1,x+2,x+2};
     9     int yy[8]= {y-1,y+1,y-2,y+2,y+2,y-2,y+1,y-1};
    10     for(int i=0; i<8; i++)
    11         if(xx[i]>=0&&yy[i]>=0&&xx[i]<=15&&yy[i]<=15)
    12         {
    13             dp[xx[i]][yy[i]]=-1;
    14         }
    15     dp[x][y]=-1;
    16 }
    17 int main()
    18 {
    19     int bx,by,mx,my;
    20     while(scanf("%d%d%d%d",&bx,&by,&mx,&my)!=EOF)
    21     {
    22         memset(dp,0,sizeof(dp));
    23         mControl(mx,my);
    24         dp[0][0]=1;
    25         for(int i=0; i<=bx; i++)
    26         {
    27             for(int j=0; j<=by; j++)
    28             {
    29                 if(dp[i][j]!=-1)
    30                 {
    31                     if(dp[i][j-1]!=-1&&j>0)
    32                         dp[i][j]+=dp[i][j-1];
    33                     if(dp[i-1][j]!=-1&&i>0)
    34                         dp[i][j]+=dp[i-1][j];
    35                 }
    36             }
    37         }
    38         printf("%d
    ",dp[bx][by]);
    39     }
    40     return 0;
    41 }
    View Code

    4. HDU 1231 最大和连续子序列(同1,1输出下标,本题是输出值)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[100005];
     4 int dp[100005];
     5 int main()
     6 {
     7 
     8     int n;
     9     while(scanf("%d",&n)!=EOF&&n)
    10     {
    11         for(int i=0; i<n; i++)
    12             scanf("%d",&a[i]);
    13         dp[0]=a[0];
    14         for(int i=1; i<n; i++)
    15         {
    16             dp[i]=max(dp[i-1]+a[i],a[i]);
    17         }
    18         int mx=-9999999;
    19         int st,en;
    20         for(int i=0; i<n; i++)
    21         {
    22             if(dp[i]>mx)
    23             {
    24                 mx=dp[i];
    25                 en=i;
    26             }
    27         }
    28         int sum=0;
    29         for(int i=en;i>=0;i--)
    30         {
    31             sum+=a[i];
    32             if(sum==mx)
    33             st=i;
    34         }
    35         if(mx<0)printf("%d %d %d
    ",0,a[0],a[n-1]);
    36         else
    37         printf("%d %d %d
    ",mx,a[st],a[en]);
    38     }
    39     return 0;
    40 }
    View Code

    5.HDU 1176 免费馅饼

    状态方程:

      特判:dp[time][0]+=max(dp[time+1][0],dp[time+1][1];

        dp[time][point]+=max(dp[time+1][point-1],dp[time+1][point],dp[time+1][point+1]) //这里没有特判最后一个位置(当位置为10,辉加到11这个位置),只要将数组多一位即可,该位置默认存放的是0,所以不会影响  

    解:用一个二位数组存放dp[time][point],从最后落下的时间向前扫描,每次存放的是 下一秒与当前 该位置能获得的最多的馅饼。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define maxx(a,b,c) (max(max(a,b),c))
     5 int dp[N][12];
     6 int main()
     7 {
     8     int n;
     9     while(scanf("%d",&n)!=EOF&&n)
    10     {
    11         memset(dp,0,sizeof(dp));
    12         int point,time,maxT=0;
    13         for(int i=1;i<=n;i++)
    14         {
    15             scanf("%d%d",&point,&time);
    16             dp[time][point]+=1;
    17             maxT=max(maxT,time);
    18         }
    19         for(int i=maxT-1;i>=0;i--)
    20         {
    21             dp[i][0]+=max(dp[i+1][0],dp[i+1][1]);
    22             for(int j=1;j<=10;j++)
    23             {
    24                 dp[i][j]+=maxx(dp[i+1][j],dp[i+1][j+1],dp[i+1][j-1]);
    25             }
    26         }
    27         printf("%d
    ",dp[0][5]);
    28     }
    29     return 0;
    30 }
    View Code

    6. POJ 1458 最长公共子序列

    参考链接:http://blog.csdn.net/u012102306/article/details/53184446

     1 #include<iostream>
     2 #include<string.h>
     3 #include<string>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAX 1002
     7 int dp[MAX][MAX];
     8 int main()
     9 {
    10     string a,b;
    11     int i,j;
    12     while(cin>>a>>b){
    13         memset(dp,0,sizeof(dp));
    14         for(i=0;i<a.length();i++)
    15             for(j=0;j<b.length();j++)
    16                 if(a[i]==b[j])
    17                     dp[i+1][j+1]=dp[i][j]+1;
    18                 else
    19                     dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
    20         cout<<dp[i][j]<<endl;
    21     }
    22     return 0;
    23 }
    View Code
     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<string>
     4 #include<iostream>
     5 using namespace std;
     6 #define N 10005
     7 int dp[N][N];
     8 int main()
     9 {
    10     string s1,s2;
    11     while(cin>>s1>>s2)
    12     {
    13         int i=s1.length(),j=s2.length();
    14         for(int i1=0; i1<=i; i1++)
    15         {
    16             for(int j1=0; j1<=j; j1++)
    17             {
    18                 if(i1==0||j1==0)
    19                     dp[i1][j1]=0;
    20                 else if(s1[i1-1]==s2[j1-1])
    21                 {
    22                     dp[i1][j1]=dp[i1-1][j1-1]+1;
    23                 }
    24                 else
    25                 {
    26                     dp[i1][j1]=max(dp[i1-1][j1],dp[i1][j1-1]);
    27                 }
    28             }
    29         }
    30         printf("%d
    ",dp[i][j]);
    31     }
    32     return 0;
    33 }
    View Code

    7. VIJOS 魔族密码 最大递增序列数

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<string>
     4 #include<string.h>
     5 #include<iostream>
     6 using namespace std;
     7 #define N 2005
     8 int dp[N];
     9 string s[N];
    10 int check(string a,string b)
    11 {
    12     int len=min(a.length(),b.length());
    13     for(int i=0; i<len; i++)
    14         if(a[i]!=b[i])return 0;
    15     return 1;
    16 }
    17 int main()
    18 {
    19     int n;
    20     while(scanf("%d",&n)!=EOF&&n)
    21     {
    22         for(int i=0; i<n; i++)
    23             cin>>s[i];
    24         memset(dp,0,sizeof(dp));
    25 
    26         for(int i=0; i<n; i++)
    27         {
    28             for(int j=0; j<i; j++)
    29                 if(check(s[i],s[j]))
    30                     dp[i]=max(dp[i],dp[j]+1);
    31         }
    32         int ans=-1e8;
    33         for(int i=0; i<n; i++)
    34             ans=max(ans,dp[i]);
    35         cout<<ans+1<<endl;
    36     }
    37     return 0;
    38 }
    View Code

     8. VIJOS 合唱队列 左向右递增,右向左递增*

     1 #include<iostream>
     2 #include<string.h>
     3 #include<algorithm>
     4 #define MAX 105
     5 using namespace std;
     6 int a[MAX],l[MAX],r[MAX];
     7 int main()
     8 {
     9     int n;
    10     cin>>n;
    11     memset(l,0,sizeof(l));
    12     memset(r,0,sizeof(r));
    13     for(int i=0; i<n; i++)
    14         cin>>a[i];
    15     for(int i=0; i<n; i++)
    16         for(int j=0; j<i; j++)
    17             if(a[i]>a[j])
    18                 l[i]=max(l[i],l[j]+1);
    19 
    20     for(int i=n-1; i>=0; i--)
    21         for(int j=n-1; j>i; j--)
    22             if(a[i]>a[j])
    23                 r[i]=max(r[i],r[j]+1);
    24     int ans=-1e8;
    25     for(int i=0; i<n; i++)
    26         ans=max(ans,r[i]+l[i]);
    27     cout<<n-(ans+1)<<endl;
    28     return 0;
    29 }
    View Code

     9. VIJOS 小胖的水果 最长公共子序列

     1 #include<iostream>
     2 #include<string.h>
     3 using namespace std;
     4 #define MAX 1005
     5 int dp[MAX][MAX];
     6 string a,b;
     7 int main()
     8 {
     9     while(cin>>a>>b)
    10     {
    11         int alen=a.length();
    12         int blen=b.length();
    13         for(int i=0; i<alen; i++)
    14         for(int j=0; j<blen; j++)
    15         {
    16             if(a[i]==b[j])
    17                 dp[i+1][j+1]=dp[i][j]+1;
    18             else
    19                 dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
    20         }
    21         cout<<alen+blen-dp[alen][blen]<<endl;
    22     }
    23     return 0;
    24 }
    View Code

     10. VIJOS 神秘的咒语 最长递增公共子序列**

     1 #include<iostream>
     2 #include<string.h>
     3 using namespace std;
     4 #define ll long long
     5 #define MAX 505
     6 ll a1[MAX],b1[MAX];
     7 int f[MAX];
     8 int main()
     9 {
    10     int T;
    11     cin>>T;
    12     while(T--)
    13     {
    14         int a,b;
    15         cin>>a;
    16         for(int i=1; i<=a; i++)
    17             cin>>a1[i];
    18         cin>>b;
    19         for(int i=1; i<=b; i++)
    20             cin>>b1[i];
    21         memset(f,0,sizeof(f));
    22         int ans=0;
    23         for(int i=1; i<=a; ++i)
    24         {
    25             int maxx=0;
    26             for(int j=1; j<=b; ++j)
    27             {
    28                 if(b1[j]<a1[i])maxx=max(maxx,f[j]);
    29                 if(b1[j]==a1[i])
    30                 {
    31                     f[j]=maxx+1;
    32                     ans=max(ans,f[j]);
    33                 }
    34             }
    35         }
    36         cout<<ans<<endl;
    37     }
    38     return 0;
    39 }
    View Code

     11. VIJOS 难解的问题 最长递增子序列(包含特定项)***

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <vector>
     6 #define Maxn 3200000
     7 using namespace std;
     8 vector<int>v;
     9 int save[Maxn];
    10 int main()
    11 {
    12     int n = 0, k = 0, knum = 0;
    13     scanf("%d%d",&n,&k);
    14     for(int i=1; i<=n; i++)
    15     {
    16         scanf("%d",&save[i]);
    17         if(i==k)
    18             knum=save[i];
    19     }
    20     for(int i=1; i<=n; i++)
    21     {
    22         if(i<k&&save[i]>=knum)
    23             continue;
    24         if(i>k&&save[i]<=knum)
    25             continue;
    26         if(v.size()==0||save[i]>v[v.size()-1])
    27             v.push_back(save[i]);
    28         else
    29         {
    30             vector<int>::iterator it=lower_bound(v.begin(),v.end(),save[i]);
    31             *it=save[i];
    32         }
    33     }
    34     printf("%d
    ",(int)v.size());
    35     return 0;
    36 }
    View Code

     12. VIJOS 雷曼兔 递减最大价值和

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<string.h>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 #define INF 0x7fffffff
     8 #define MAX 3002
     9 #define LL long long
    10 struct P
    11 {
    12     int x,y,h;
    13 } p[MAX];
    14 int dp[MAX];
    15 bool cmp(const P a,const P b)
    16 {
    17     return a.h<b.h;
    18 }
    19 int main()
    20 {
    21     int n;
    22     cin>>n;
    23     int l = 1;
    24     for(int i = 1; i <= n; ++i)
    25         for(int j = 1; j <= n; ++j)
    26         {
    27             cin>>p[l].h;
    28             p[l].x=i;
    29             p[l].y=j;
    30             l++;
    31         }
    32     sort(p,p+l,cmp);
    33     dp[1]=0;
    34     for(int i = 2; i <= n*n; ++i)
    35     {
    36         int tem = 0;
    37         for(int j = 1; j < i; ++j)
    38         {
    39             int t = abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);
    40             t *= t;
    41             tem = max( tem,t+dp[j]);
    42         }
    43         dp[i] = tem;
    44     }
    45     cout<<dp[n*n]<<endl;
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    记录Log4Net的使用
    利用Ihttpmodel实现网站缓存,解决Server.Transfer 直接输出HTML源代码的问题
    ASP.NET利用byte检测上传图片安全
    通过cmd命令安装、卸载、启动和停止Windows Service(InstallUtil.exe)-大壮他哥
    winform利用代码将控件置于顶端底端
    查询
    字符数组实例化
    三维数组
    填充和批量替换
    遍历二维数组
  • 原文地址:https://www.cnblogs.com/A--Q/p/6641568.html
Copyright © 2020-2023  润新知