动态规划求解0-1背包问题
0-1背包问题是: 一个背包能承受的最大容量为max_weight, 现在有n个物品, 它们的重量分别是{w1,w2,w3,......wn}, 和价值分别是{v1,v2,......vn}, 现在要求在满足背包装载的物品不超过最大容量的前提下,保证装载的物品的价值最大?
动态规划求解过程可以这样理解:
对于前i件物品,背包剩余容量为j时,所取得的最大价值(此时称为状态3)只依赖于两个状态。
状态1:前i-1件物品,背包剩余容量为j。在该状态下,只要不选第i个物品,就可以转换到状态3。
状态2:前i-1件物品,背包剩余容量为j-w[i]。在该状态下,选第i个物品,也可以转换到状态3。
因为,这里要求最大价值,所以只要从状态1和状态2中选择最大价值较大的一个即可。
状态转换方程:
dp( i,j ) = Max( dp( i-1, j ), dp( i-1, j-w[i] ) + v[i] )
dp( i,j )表示前i件物品,背包剩余容量为j时,所取得的最大价值。
下面是java的demo代码:
private int[] v; private int[] w; private static int[][] c; private int weight; private int[] flag = new int[5]; public Greedy(int weight, int[] v, int[] w, int maxWeight) { this.w = w; this.v = v; this.weight = weight; this.c = new int[v.length][this.weight + 1]; } public void solve() { int len = w.length; for (int i = 1; i < len; i++) { for (int j = 1; j <= weight; j++) { //第i件物品要么放,要么不放 //如果第i件物品不放的话,就相当于求前i-1件物体放入容量为j的背包获得的最大价值 //如果第i件物品放进去的话,就相当于求前i-1件物体放入容量为j-w[i]的背包获得的最大价值 if (w[i] > j) { c[i][j] = c[i - 1][j]; } else { // j > w[i] if (c[i - 1][j] > c[i - 1][j - w[i]] + v[i]) { c[i][j] = c[i - 1][j]; } else { c[i][j] = c[i - 1][j - w[i]] + v[i]; } } } } //下面求解哪个物品应该放进背包 int i = v.length - 1, j = weight; while (c[i][j] != 0) { if (c[i - 1][j - w[i]] + v[i] == c[i][j]) { flag[i] = 1; j = j - w[i]; i--; } } for (i = 1; i < v.length; i++) { if (flag[i] == 1) { System.out.print("重量" + w[i]); System.out.println("价值为" + v[i]); } } } public static void main(String[] args) { int[] v = {0, 4, 5, 6}; int[] w = {0, 3, 4, 5}; int weight = 10; Greedy knapsack = new Greedy(weight, v, w, weight); knapsack.solve(); }