动态规划处理01背包问题
对于物品X, 重量, 价值和背包总容量为以下数值的情况下, 求在背包容量限制下得到最大价值的物品组合方式
5个物品,(重量w,价值v)分别为:(5,12),(4,3),(7,10),(2,3),(6,6)
1. 假设最优答案
我们假设最优答案为00011。这样根据动态规划要求,考虑最优子问题。一般考虑子问题都是减少问题包含元素数量,同时保持子问题与原问题属于同种问题,只是考虑数量减少了。比如我们减少第五个物品, 那么子问题就是
4个物品,(重量w,价值v)分别为:(5,12),(4,3),(7,10),(2,3)
2. 找到原问题与子问题之间联系
如果00011为原问题最优解, 那么0001就是子问题最优解. 如果0001不是子问题最优解, 假设0101为子问题最优解, 那原问题最优解就是01011, 与我们假设相悖. 那么从子问题到原问题要经过什么样考虑? 假定现在已经找到子问题最优解, 到原问题解我们只需考虑第五个物品是取还是不取. 如果取, 那么取以后背包空余量减少, 背包价值增大, 如果弃, 那么子问题的条件有变化(空间增大了), 可能有更优的子问题最优解, 背包价值也会变, 所以要比较这两者哪个价值更大:
1) 如果最优解包含了物品n,即物(n)=1,那么其余物1,物2,…,物(n-1) 一定构成子问题1,2,…,n-1在背包容量W-w(n)时的最优解
2) 如果最优解不包含物品n,即物(n)=0,那么其余物1,物2,…,物(n-1)一定构成子问题1,2,…,n-1在背包容量W时的最优解。
3. 公式的建立
根据上一步, 就能知道, 在加上第五个物品后, 只需要判断两种情况下的价值, 就能知道包含第五个物品时的最优解, 即
1) 物1~物(n-1)在背包容量W-w(n)时的最大价值加上第五个物品的价值
2) 在背包容量为W时, 物1~物(n-1)的最大价值
所以有
cell[i][j] = max( cell[i-1][j-w[i]] + v[i], cell[i-1][j]) {i,j|0< i <=n,0<= j <=total}
3. 代码实现, 使用Java语言
public static void main(String[] args) { int[] w = {2, 2, 6, 5, 4, 3, 7}; //weight int[] v = {6, 3, 5, 4, 6, 6, 9}; //value int c = 10; //capcity int[] x = new int[w.length]; // record int[][] m = new int[w.length][c+1]; for (int i = 0; i < w.length; i++) { // for each w[i] for (int j = 0; j <= c; j++) { // for each capacity if (j < w[i]) { int tmp = (i - 1) < 0 ? 0 : m[i - 1][j]; m[i][j] = tmp; continue; } int v1 = (i - 1) < 0 ? v[i] : m[i - 1][j - w[i]] + v[i]; int v2 = (i - 1) < 0 ? 0 : m[i - 1][j]; if (v1 > v2) { m[i][j] = v1; } else { m[i][j] = v2; } } } for (int i = m.length - 1; i >= 0; i--) { for (int j = 0; j < m[i].length; j++) { System.out.print(String.format("%2d ",m[i][j])); } System.out.println(); } int cap = c; for (int i = w.length - 1; i >= 0; i--) { if (i == 0) { if (m[i][cap] > 0) { x[i] = 1; } } else { if (m[i][cap] > m[i - 1][cap]) { x[i] = 1; cap = cap - w[i]; } } } for (int i = 0; i < x.length; i++) { if (x[i] != 0) { System.out.println(i + ":" + w[i] + ":" + v[i]); } } }
运行的结果
0 0 6 6 9 12 12 15 15 18 18 0 0 6 6 9 12 12 15 15 18 18 0 0 6 6 9 9 12 12 15 15 15 0 0 6 6 9 9 9 10 11 13 14 0 0 6 6 9 9 9 9 11 11 14 0 0 6 6 9 9 9 9 9 9 9 0 0 6 6 6 6 6 6 6 6 6
0:2:6 4:4:6 5:3:6