kuangbin带你飞dp专题-基础dp

dp

HDU - 1257 最少拦截系统

 最长递增子序列

 1 #include<iostream>
 2 using namespace std;
 3 const int maxn=1e7;
 4 int a[maxn],dp[maxn],n;
 5 
 6 int main()
 7 {
 8     while(cin>>n) {
 9         for (int i = 1; i <= n; i++)cin >> a[i];
10         for (int i = 1; i <= n; i++)dp[i] = 1;
11         for (int i = 2; i <= n; i++)
12             for (int j = 1; j < i; j++) {
13                 if (a[i] > a[j])
14                     dp[i] = max(dp[i], dp[j] + 1);
15             }
16         int ans = 0;
17         for (int i = 1; i <= n; i++)ans = max(ans, dp[i]);
18         cout << ans << endl;
19     }
20     return 0;
21 }

 

HDU - 1029 Ignatius and the Princess IV

 

HDU - 1069 Monkey and Banana

 

POJ - 1458 Common Subsequence

 最长公共子序列

dp[i][j] = 0                                        i==0 || j==0

          = max(dp[i][j], dp[i-1][j-1]+1)    a[i-1]==b[i-1] 

          = max(dp[i-1][j], dp[i][j-1])       a[i-1]!=b[i-1] 

 1 #include<string>
 2 #include <iostream>
 3 using namespace std;
 4 const int maxn=1e4+2;
 5 int dp[maxn][maxn];
 6 int main()
 7 {
 8     string s1,s2;
 9     while(cin>>s1>>s2)
10     {
11         int len1=s1.size();
12         int len2=s2.size();
13         for(int i=0;i<=len1;i++)
14             for(int j=0;j<=len2;j++)
15                 dp[i][j]=0;
16         for(int i=0;i<=len1;i++)
17             for(int j=0;j<=len2;j++)
18             {
19                 if((i==0)||(j==0))continue;
20                 else if(s1[i-1]==s2[j-1])
21                     dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
22                 else
23                 {
24                     dp[i][j]=max(dp[i][j],dp[i][j-1]);
25                     dp[i][j]=max(dp[i][j],dp[i-1][j]);
26                 }
27             }
28         cout<<dp[len1][len2]<<endl;
29     }
30     return 0;
31 }

 

POJ - 2533 Longest Ordered Subsequence

 1 while(cin>>n)
 2 {
 3         for(int i=1;i<=n;i++)cin>>a[i];
 4         for(int i=1;i<=n;i++)dp[i]=1;
 5         for(int i=2;i<=n;i++)
 6         {
 7             for(int j=1;j<i;j++)
 8             {
 9                 if(a[i]>a[j])
10                     dp[i]=max(dp[i],dp[j]+1);
11             }
12             ans=max(ans,dp[i]);
13         }
14         cout<<ans<<endl;
15 }

HDU - 1003 Max Sum

 1 #include<iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 const int maxn=1e5+2;
 6 long long dp[maxn],a[maxn],ans=-0xfffffffffffff;
 7 int n,t=0,T=0,l,r;
 8 
 9 int main()
10 {
11     cin>>n;
12     while(n--)
13     {
14         cin>>t;
15         T++;
16         for(int i=1;i<=t;i++)cin>>a[i];
17         for(int i=-1;i<=t;i++)dp[i]=a[i];
18         for(int i=2;i<=t;i++)
19             dp[i]=max(dp[i-1]+a[i],dp[i]);
20         for(int i=1;i<=t;i++)
21         {
22             if(dp[i]>ans){
23                 ans=max(ans,dp[i]);
24                 r=i;
25             }
26         }
27         long long sum=0;
28         for(int i=r;i>=1;i--) {
29             sum += a[i];
30             if (sum == ans) {
31                 l = i;
32             }
33         }
34         if(T!=1)cout<<endl;
35         cout<<"Case "<<T<<":"<<endl;
36         cout<<ans<<" "<<l<<" "<<r<<endl;
37     }
38     return 0;
39 }

HDU - 3421 Max Sum II

 

HDU - 1024 Max Sum Plus Plus

 

HDU - 1244 Max Sum Plus Plus Plus

 

HDU - 1087 Super Jumping! Jumping! Jumping!

 

HDU - 1114 Piggy-Bank

 

HDU - 1176 免费馅饼

 

HDU - 1160 FatMouse's Speed

 

POJ - 1661 Help Jimmy

 

HDU - 1260 Tickets

 

POJ - 3186 Treats for the Cows

 

HDU - 1078 FatMouse and Cheese

 

HDU - 2859 Phalanx

 

POJ - 3616 Milking Time

 

POJ - 3666 Making the Grade

 

HDU - 1074 Doing Homework

 

UVA - 11367 Full Tank?

 

POJ - 1015 Jury Compromise 

题意:选m人:控方和辩方会根据对候选人的喜欢程度,给候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分D和控方总分P的差的绝对值|D-P|最小。如果有多种选择方案的 |D-P| 值相同,那么选辩控双方总分之和D+P最大的方案。

输出:要求输出这m个人的辩方总值D和控方总值P,并升序输出他们的编号

思路:

辩方总分和控方总分之差称为“辩控差”,辩方总分和控方总分之和称为“辩控和”。

第i个候选人的辩方总分和控方总分之差记为V(i),之和记为S(i)。

状态:dp[j][k]表示,取j个候选人,使其辩控差为k的所有方案中,辩控和最大的方案的辩控和。

         如果没法选j个人,使其辩控差为k,那么dp(j, k)的值就为-1。

求:dp[m][k] (-20×m ≤ k ≤ 20×m)

转移方程:dp[j][k]= max ( dp[j-1][k-V[i]]+S[i], dp[j][k] )

方案dp[j][k]是由某个可行的方案 dp[j-1][x] 演化而来,可行方案 dp[j-1][x] 能演化成方案 dp[j][k] 的必要条件是:存在某个候选人i,i 在方案 dp[j-1][x] 中没有被选上,且x+V(i) = k。在所有满足该必要条件的dp[j-1][x]中,选出 dp[j-1][x]+ S(i) 的值最大的。

程序中没有求绝对值而是将辩控差都加上修正值fix=400,以免下标为负数导致出错,此时初始条件修正为dp[0][fix] = 0,其他均为-1。DP后,从第m行的dp(m, fix)开始往两边搜索最小|D-P| 即可,第一个不为dp[m][k]!=-1的位置k就是最小|D-P|的所在。

 1 #include <iostream>
#include <string.h> 2 #include <algorithm> 3 using namespace std; 4 int f[30][1000]; 5 //f[j][k]表示:取j个候选人,使其辩控差为k的方案中 6 //辩控和最大的那个方案(该方案称为“方案f(j,k)”)的控辩和 7 int Path[30][1000]; 8 //Path数组用来记录选了哪些人 9 //方案f(j,k)中最后选的那个候选人的编号,记在Path[j][k]中 10 int P[300];//控方打分 11 int D[300]; //辩方打分 12 13 int Answer[30];//存放最终方案的人选 14 15 int main() 16 { 17 int i,j,k; 18 int t1,t2; 19 int n,m; 20 int MinP_D;//辩控双方总分一样时的辩控差 21 int Case;//测试数据编号 22 Case=0; 23 while(scanf("%d %d",&n,&m)) 24 { 25 if(n==0&&m==0)break; 26 Case++; 27 for(i=1;i<=n;i++) 28 scanf("%d %d",&P[i],&D[i]); 29 memset(f,-1,sizeof(f)); 30 memset(Path,0,sizeof(Path)); 31 MinP_D=m*20;//题目中的辩控差为0,对应于程序中的辩控差为m*20 32 f[0][MinP_D]=0; 33 for(j=0;j<m;j++)//每次循环选出第j个人,共要选出m人 34 { 35 for(k=0;k<=MinP_D*2;k++)//可能的辩控差为[0,nMinP_D*2] 36 if(f[j][k]>=0)//方案f[j][k]可行 37 { 38 for(i=1;i<=n;i++) 39 if(f[j][k]+P[i]+D[i]>f[j+1][k+P[i]-D[i]]) 40 { 41 t1=j;t2=k; 42 while(t1>0&&Path[t1][t2]!=i)//验证i是否在前面出现过 43 { 44 t2-=P[Path[t1][t2]]-D[Path[t1][t2]]; 45 t1--; 46 } 47 if(t1==0) 48 { 49 f[j+1][k+P[i]-D[i]]=f[j][k]+P[i]+D[i]; 50 Path[j+1][k+P[i]-D[i]]=i; 51 } 52 } 53 } 54 } 55 i=MinP_D; 56 j=0; 57 while(f[m][i+j]<0&&f[m][i-j]<0) // 从中间向两边开始找辩控差最小和最大 58 j++; 59 if(f[m][i+j]>f[m][i-j]) 60 k=i+j; 61 else 62 k=i-j; 63 printf("Jury #%d\n",Case); 64 printf("Best jury has value %d for prosecution and value %d for defence:\n",(k-MinP_D+f[m][k])/2,(f[m][k]-k+MinP_D)/2); 65 for(i=1;i<=m;i++) 66 { 67 Answer[i]=Path[m-i+1][k]; 68 k-=P[Answer[i]]-D[Answer[i]]; 69 } 70 sort(Answer+1,Answer+1+m); 71 for(i=1;i<=m;i++) 72 printf(" %d",Answer[i]); 73 printf("\n\n"); 74 } 75 return 0; 76 }

 

posted @ 2019-01-27 13:28  demianzhang  阅读(352)  评论(0编辑  收藏  举报