顾名思义,二维费用的背包中的每种物品有两种费用
设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 }
可以看出二维背包是对前面所述的几种背包的一个综合的考量