【发布时间】:2018-05-16 15:19:05
【问题描述】:
给定问题:
0/1-背包问题,n 个项目,每个项目的重量为 w_i,价值为 v_i。求权重总和为权重 W 的项目的最大总价值。
但是有两个限制:
- 背包中所有物品的总重量需要正好W。
- 总项目数量必须是偶数。
我想找到一个同时关注这两个约束的算法。我已经知道如何同时关注其中之一。
这是我的实现,它注意约束 1(精确重量 W):
public class KnapSackExactWeight {
public static void main(String[] args) {
int[] w = new int[] {4, 1, 5, 8, 3, 9, 2}; //weights
int[] v = new int[] {2, 12, 8, 9, 3, 4, 3}; //values
int n = w.length;
int W = 10; // W (max weight)
int[][] DP = new int[n+1][W+1];
for(int i = 1; i < n+1; i++) {
for(int j = 0; j < W+1; j++) {
if(i == 0 || j == 0) {
DP[i][j] = 0;
} else if (j - w[i-1] >= 0) {
DP[i][j] = Math.max(DP[i-1][j], DP[i-1][j - w[i-1]] + v[i-1]);
} else {
DP[i][j] = -Integer.MAX_VALUE;
}
}
}
System.out.println("Result: " + DP[n][W]);
}
}
Result: 22
这是我的实现,它考虑了约束 2(即使项目数量):
public class KnapSackEvenAmount {
public static void main(String[] args) {
int[] weights = new int[] {4, 1, 5, 8, 3, 9, 2}; //weights
int[] values = new int[] {2, 12, 8, 9, 3, 4, 3}; //values
int n = weights.length;
int W = 10;
int[][] DP_odd = new int[n+1][W+1];
int[][] DP_even = new int[n+1][W+1];
for(int i = 0; i < n+1; i++) {
for(int j = 0; j < W+1; j++) {
DP_even[i][j] = -1;
DP_odd[i][j] = -1;
if(i == 0 || j == 0) {
DP_odd[i][j] = -1;
DP_even[i][j] = 0;
} else if(j - weights[i-1] >= 0) {
if(DP_odd[i-1][j - weights[i-1]] >= 0) {
DP_even[i][j] = Math.max(DP_even[i-1][j], DP_odd[i-1][j - weights[i-1]] + values[i-1]);
}
if(DP_even[i-1][j - weights[i-1]] >= 0) {
DP_odd[i][j] = Math.max(DP_odd[i-1][j], DP_even[i-1][j - weights[i-1]] + values[i-1]);
}
}
if(i > 0) {
DP_odd[i][j] = Math.max(DP_odd[i][j], DP_odd[i-1][j]);
DP_even[i][j] = Math.max(DP_even[i][j], DP_even[i-1][j]);
}
}
}
System.out.println("Result: " + DP_even[n][W]);
}
}
Result: 21
对此的想法:我使用两个 DP 表(DP_even 和 DP_odd),并为 DP_odd 中包含奇数物品的背包和 DP_even 中包含偶数物品的背包保存最佳解决方案。
现在我的问题是如何实现这两个约束一起工作。有没有办法解决这个问题?
(如果我的问题有什么不清楚的地方,尽管问!)
【问题讨论】:
-
第二种算法有什么问题?你能举一个它没有给出正确答案的例子吗?在我看来,它似乎已经包含了这两个约束?
-
现在它使用 w[1] (=1) 和 w[3] (=8),所以第一个约束不是 1+8=9 != 10。结果应该如果两个约束都考虑在内,则为 20(w[0]、w[1]、w[4] 和 w[6],它们的重量为 10,值为 20)
标签: java algorithm dynamic-programming knapsack-problem