前面4篇博客已经将几种基础背包问题介绍,本文主要对“二维费用”背包问题进行介绍。“二维费用”背包问题,较前面几种背包问题主要是对每类物品增加了一维费用,用一个简单的例子来说,即选取某一个物品的同时增加了一个附属物品,同时对附属物品的费用也有了限制,通过这种思维,可以将“二维费用”背包转换为“01基础背包”问题,按照“01基础背包”方程可以得到该基础方程:
c[i][j][k] = max(c[i-1][j-w[i-1]][k-w2[i-1]] + v[i-1], c[i-1][j][k]);
该方程只是在”01基础背包“方程的基础上增加了一维,其代码实现也较为简单,以下将通过一个具体的例子来说明。
假设:在选取a、b、c三种物品放入背包时,每类物品由于均有附属物,所以对主件和附件均有容量要求,主件容量要求不超过8 Kg,而附件容量不超过5 Kg,在该限制条件下,求可以获取的最大价值。
具体题目如下:
可能出现的情况:
上述表格由上到下、由左到右生成,由于主件、附件捆绑在一起,所以在选取时需要双重考虑。其Java实现代码如下:
//在01基础背包的基础上,添加一维数组来进行多重考虑
private static int[][] BP_method05_1D(int m,int m2,int n,int[] w,int[] w2,int[] v){
int c[][] = new int[m+1][m2+1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
c[i][j] = 0;
}
}
for (int i = 0; i < n; i++) {//限定物品种类,无重复
for (int j = m; j >= w[i]; j--) {//限定主件总重量
for (int k = m2; k >= w2[i]; k--) {//限定附件重量
c[j][k] = Math.max(c[j-w[i]][k-w2[i]] + v[i], c[j][k]);
}
}
}
return c;
}
//因为新增加了一维判断,所以在原来的二维解法基础上形成三维解法
private static int[][][] BP_method05_2D(int m1,int m2,int n,int[] w, int[] w2,int[] v){
int c[][][] = new int[n+1][m1+1][m2+1];
for (int i = 0; i < n+1; i++) {
c[i][0][0] = 0;
}
for (int i = 0; i < n; i++) {
c[0][i][0] = 0;
}
for (int i = 1; i <= n; i++) {//限定物品种类,无重复
for (int j = 1; j <= m1; j++) {//限定主件总重量
for (int k = 0; k <= m2; k++) {//限定附件总重量
if (j >= w[i-1] && k >= w2[i-1]) {
c[i][j][k] = Math.max(c[i-1][j-w[i-1]][k-w2[i-1]] + v[i-1], c[i-1][j][k]);
}else {
c[i][j][k] = c[i-1][j][k];
}
}
}
}
return c;
}
其输出结果如下:
二维解法:
0 0 0 0 0
0 0 0 0 0
0 4 4 4 4
0 4 4 5 5
0 4 6 6 6
0 4 6 6 6
0 4 6 6 6
0 4 6 6 10
三维解法:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 4 0 0 4 4 4 4 0 0 4 4 4 4 0 0 4 4 4 4 0 0 4 4 4 4 0 0 4 4 4 4
0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 4 0 0 4 4 5 5 0 0 4 4 5 5 0 0 4 4 5 5 0 0 4 4 5 5 0 0 4 4 5 5
0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 4 0 0 4 4 5 5 0 0 4 6 6 6 0 0 4 6 6 6 0 0 4 6 6 6 0 0 4 6 6 10