之前做过的传纸条那道题就是双重动态规划的典型应用,题意就不描述了,直接贴一下以前写过的,经典代码
1 #include<iostream> 2 using namespace std; 3 const int maxn=55,maxm=55; 4 int MAX(int x,int y) 5 { 6 return x>y?x:y; 7 } 8 int MAX1(int x,int y,int z,int w) 9 { 10 return MAX(MAX(x,y),MAX(z,w)); 11 } 12 int m,n; 13 int ans=0; 14 // 15 int a[maxm][maxn]; 16 int f[maxm][maxn][maxm][maxn]; 17 void dp() 18 { 19 for(int i=1;i<=m;i++) 20 { 21 for(int j=1;j<=n;j++) 22 { 23 for(int k=1;k<=m;k++) 24 { 25 for(int l=1;l<=n;l++) 26 { 27 if(j==l||i==k) continue; 28 f[i][j][k][l]=a[i][j]+a[k][l]+MAX1(f[i-1][j][k-1][l],f[i][j-1][k-1][l],f[i-1][j][k][l-1],f[i][j-1][k][l-1]); 29 } 30 } 31 } 32 } 33 ans=a[m][n]+MAX(f[m-1][n][m][n-1],f[m][n-1][m-1][n]); 34 } 35 36 int main() 37 { 38 cin>>m>>n; 39 for(int i=1;i<=m;i++) 40 for(int j=1;j<=n;j++) 41 cin>>a[i][j]; 42 dp(); 43 cout<<ans<<endl; 44 return 0; 45 }
我记得当时写过记忆化+dp的,这里不贴了
Codevs1444
把歌曲分堆,然后各自求最优装载,分别用01背包算法。
由于不知道如何分堆才会产生最优解,所以第一次动态规划算出每个区间段的最优装载,然后第二个动态规划求出最优的分堆。这题可以用双重动态规划求解。
N(1 <= N <= 20)首歌的版权。你打算从中精选一些歌曲,发行M(1 <= M <= 20)张CD。每一张CD最多可以容纳T(1 <= T <= 20)分钟的音乐,一首歌不能分装在两张CD中
第一行: 三个整数:N, T, M.
第二行: N个整数,分别表示每首歌的长度,按创作时间顺序排列。
1 #include<iostream> 2 using namespace std; 3 const int maxn=21; 4 long maxx[maxn][maxn]; 5 long best[maxn][maxn]; 6 long best2[maxn]; 7 int main() 8 { 9 long a[maxn]; 10 int n,t,m; 11 cin>>n>>t>>m; 12 for(int i=1;i<=n;i++) 13 { 14 cin>>a[i]; 15 } 16 17 for(int i=1;i<=n;i++) 18 { 19 for(int i=0;i<=t;i++) 20 { 21 best2[i]=0; 22 } 23 for(int j=i;j<=n;j++) 24 { 25 for(int k=t;k>=a[j];k--) 26 { 27 if(best2[k-a[j]]+1>best2[k]) 28 best2[k]=best2[k-a[j]]+1; 29 } 30 maxx[i][j]=best2[t]; 31 } 32 } 33 for(int i=1;i<=n;i++) 34 { 35 best[i][1]=maxx[1][i]; 36 for(int j=2;j<=m;j++) 37 { 38 for(int k=i;k>=1;k--) 39 { 40 if(best[k][j-1]+maxx[k+1][i]>best[i][j]) 41 best[i][j]=best[k][j-1]+maxx[k+1][i]; 42 } 43 } 44 } 45 cout<<best[n][m]<<endl; 46 return 0; 47 }