从零开始的DP练习册
Posted shingen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始的DP练习册相关的知识,希望对你有一定的参考价值。
此文为博主原创,转载时请通知博主,并把原文链接放在正文醒目位置。
因为我确实把DP忘得一干二净...就当新学了。无解析无责任,只贴题目来源和AC代码。
1.数字三角形
记忆化搜索还是很容易想的,这个代码是我早期的代码orz
1 #include<iostream> 2 #include<cstdio> 3 //code by kamigen 4 using namespace std; 5 6 int num[1000][1000]; 7 8 int main() 9 { 10 int r; 11 scanf("%d",&r); 12 for(int i = 1;i <= r;i ++) 13 { 14 for(int j = 1;j <= i;j ++) 15 scanf("%d",&num[i][j]); 16 } 17 for(int i = r-1;i > 0;i --) 18 { 19 for(int j = 1;j <= i+1;j ++) 20 { 21 num[i][j] += max(num[i+1][j],num[i+1][j+1]); 22 } 23 } 24 printf("%d",num[1][1]); 25 return 0; 26 }
2.USACO 邮票
完全背包。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 //code by kamigen 6 inline void read(int &x) 7 { 8 char ch = getchar(),c = ch;x = 0; 9 while(ch < ‘0‘ || ch >‘9‘) c = ch,ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘) x = x*10+ch-‘0‘,ch = getchar(); 11 if(c == ‘-‘) x = -x; 12 } 13 14 int dp[2000005],stamp[300],tot[300]; 15 int k,n,mx,ans,V; 16 17 inline int Max(int a,int b) 18 {return a>b?a:b;} 19 inline int Min(int a,int b) 20 {return a<b?a:b;} 21 22 int main() 23 { 24 memset(dp,0x3f,sizeof(dp)); 25 dp[0] = 0; 26 read(k),read(n); 27 for(int i = 1;i <= n;++ i) 28 read(stamp[i]),mx = Max(mx,stamp[i]); 29 V = mx*k; 30 for(int i = 1;i <= n;++ i) 31 for(int j = stamp[i];j <= V;++ j) 32 dp[j] = Min(dp[j],dp[j-stamp[i]]+1); 33 for(int i = 1;i <= V;++ i) 34 if(dp[i] <= k) ans ++; 35 else break; 36 printf("%d\n",ans); 37 return 0; 38 }
3.USACO 赚钱
完全背包。 不知道为什么这题好冷啊...我给它写了个题解。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 //code by kamigen 6 inline void read(int &x) 7 { 8 char ch = getchar(),c = ch;x = 0; 9 while(ch < ‘0‘ || ch >‘9‘) c = ch,ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘) x = x*10+ch-‘0‘,ch = getchar(); 11 if(c == ‘-‘) x = -x; 12 } 13 14 int n,m,tmp,ans; 15 int w[110],val[110],dp[100005]; 16 17 inline int Max(int a,int b) 18 {return a>b?a:b;} 19 20 int main() 21 { 22 read(n),read(m); 23 for(int i = 1;i <= n;++ i) 24 { 25 read(w[i]),read(tmp); 26 val[i] = tmp-w[i]; 27 } 28 //dp[i]表示花费i元买古董的最大利润 29 for(int i = 1;i <= n;++ i) 30 for(int j = w[i];j <= m;++ j) 31 dp[j] = Max(dp[j],dp[j-w[i]]+val[i]); 32 for(int i = 1;i <= m;++ i) 33 ans = Max(ans,dp[i]-i+m); 34 printf("%d\n",ans); 35 return 0; 36 }
一个普通的、略有难度(对我来说)的DP。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 //code by kamigen 6 inline void read(int &x) 7 { 8 char ch = getchar(),c = ch;x = 0; 9 while(ch < ‘0‘ || ch >‘9‘) c = ch,ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘) x = x*10+ch-‘0‘,ch = getchar(); 11 if(c == ‘-‘) x = -x; 12 } 13 14 int t,n,k,last,ans; 15 int dis[110],p[110],dp[110]; 16 17 inline int Max(int a,int b) 18 {return a>b?a:b;} 19 20 int main() 21 { 22 read(t); 23 while(t --) 24 { 25 memset(dp,0,sizeof(dp)); 26 read(n),read(k); 27 for(int i = 1;i <= n;++ i) 28 read(dis[i]); 29 for(int i = 1;i <= n;++ i) 30 read(p[i]); 31 for(int i = 1;i <= n;++ i) 32 { 33 for(int j = 1;j <= i;++ j) 34 if(dis[i]-dis[j] > k) 35 dp[i] = Max(dp[i],dp[j]); 36 dp[i] += p[i]; 37 } 38 ans = 0; 39 for(int i = 1;i <= n;++ i) 40 ans = Max(dp[i],ans); 41 printf("%d\n",ans); 42 } 43 return 0; 44 }
一个普通的、略有难度(对我来说)的DP。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 //code by kamigen 6 inline void read(int &x) 7 { 8 char ch = getchar(),c = ch;x = 0; 9 while(ch < ‘0‘ || ch >‘9‘) c = ch,ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘) x = x*10+ch-‘0‘,ch = getchar(); 11 if(c == ‘-‘) x = -x; 12 } 13 14 int t,l,r,len1,len2; 15 int dp[1010][1010]; 16 //dp[i][j]表示s1前i位与s2前j位的距离 17 char s1[1010],s2[1010]; 18 19 inline int Min(int a,int b) 20 {return a<b?a:b;} 21 22 inline int Max(int a,int b) 23 {return a>b?a:b;} 24 25 int main() 26 { 27 read(t); 28 while(t --) 29 { 30 scanf("%s",s1+1); 31 scanf("%s",s2+1); 32 memset(dp,0,sizeof(dp)); 33 len1 = strlen(s1+1),len2 = strlen(s2+1); 34 for(int i = 1;i <= len1;++ i) dp[i][0] = i; 35 for(int i = 1;i <= len2;++ i) dp[0][i] = i; 36 for(int l = 1;l <= len1;++ l) 37 for(int r = 1;r <= len2;++ r) 38 { 39 if(s1[l] == s2[r]) dp[l][r] = dp[l-1][r-1]; 40 else 41 dp[l][r] = Min(dp[l-1][r],Min(dp[l-1][r-1],dp[l][r-1]))+1; 42 } 43 printf("%d\n",dp[len1][len2]); 44 } 45 return 0; 46 }
坐标模型,比4和5简单多了。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 //code by kamigen 6 inline void read(int &x) 7 { 8 char ch = getchar(),c = ch;x = 0; 9 while(ch < ‘0‘ || ch >‘9‘) c = ch,ch = getchar(); 10 while(ch <= ‘9‘ && ch >= ‘0‘) x = x*10+ch-‘0‘,ch = getchar(); 11 if(c == ‘-‘) x = -x; 12 } 13 14 int n; 15 int mp[110][110],dp[110][110]; 16 17 inline int Min(int a,int b) 18 {return a<b?a:b;} 19 20 int main() 21 { 22 read(n); 23 for(int i = 1;i <= n;++ i) 24 for(int j = 1;j <= n;++ j) 25 read(mp[i][j]); 26 memset(dp,0x3f,sizeof(dp)); 27 dp[0][0] = 0,dp[0][1] = 0,dp[1][0] = 0; 28 for(int i = 1;i <= n;++ i) 29 for(int j = 1;j <= n;++ j) 30 dp[i][j] = Min(dp[i-1][j],dp[i][j-1])+mp[i][j]; 31 printf("%d\n",dp[n][n]); 32 return 0; 33 }
7.等待更新
以上是关于从零开始的DP练习册的主要内容,如果未能解决你的问题,请参考以下文章