动态规划:二维费用背包

顾名思义,二维费用的背包中的每种物品有两种费用

设f[i][v][u]表示前i件物品付出两种代价分别为v和u时可获得的最大价值

那么我们很容易给出状态转移方程,加一维状态即可

f[i][v][u]=max{f[i-1][v][u],f[i-1][v-a[i]][u-b[i]]+w[i]}

在这里,如果每种物品只可以取一次采用类似于01背包滚动数组的循环方式,即逆序循环

如果每种物品可以取无数次采用完全背包滚动数组的循环方式,顺序循环

如果有多重背包的方式进行二进制优化,拆分物品

除此之外,我们要考虑满包的情况

下面我们以RQNOJ中多多看DVD(加强版)这道题为例,来举一个具体的例子

 1 //M是第一个限制条件,每个的费用均为1,满包 
 2 //L是第二个限制条件, 每个的费用为t[i]
 3 #include<iostream>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int INF=0x7fffffff;
 8 const int maxn=105,maxm=105,maxl=1005;
 9 int N,M,L;
10 int t[maxn],w[maxn];
11 int ans=0;
12 int f[maxl][maxn];
13 void dp()
14 {
15     for(int i=0;i<=L;i++)
16     for(int j=0;j<=M;j++)
17         f[i][j]=-INF;
18     for(int i=0;i<=L;i++)
19         f[i][0]=0;
20     //01背包逆向,完全背包正向 
21     for(int i=1;i<=N;i++)
22     for(int j=L;j>=t[i];j--)
23     for(int k=M;k>=1;k--)
24         f[j][k]=max(f[j][k],f[j-t[i]][k-1]+w[i]);
25     ans=f[L][M];
26     if(ans<0)
27         ans=0;
28 }
29 int main()
30 {
31     cin>>N>>M>>L;
32     for(int i=1;i<=N;i++)
33         cin>>t[i]>>w[i];
34     dp();
35     cout<<ans<<endl;
36     return 0;
37 }

可以看出二维背包是对前面所述的几种背包的一个综合的考量

posted @ 2018-07-14 10:09  静听风吟。  阅读(965)  评论(0编辑  收藏  举报