动态规划:双重DP

之前做过的传纸条那道题就是双重动态规划的典型应用,题意就不描述了,直接贴一下以前写过的,经典代码

 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 }  

 

转载于:https://www.cnblogs.com/aininot260/p/9627075.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值