給定問題:有2個約束的揹包
0/1-揹包問題,每個項目有n個權重w_i和值v_i。查找其權重之和高達體重W.
但有兩個constraits的最大總價值:
- 總重量所有項目在揹包的需要是準確W¯¯。
- 總計數量項目必須是甚至。
我想找到一個關注兩個約束的算法。我已經發現我一次可以關注其中的一個。
這是我實現它注重constrait 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
這裏是我實現這需要constrait 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),所以第一個constrait不是真的,因爲1 + 8 = 9!= 10。如果兩個constrait都被採用,結果應該是20 (w [0],w [1],w [4]和w [6],它們的權重爲10,並且其值爲20) – zutru