public class Main { /** * * @param value * @param weight * @param c 背包容量 * @param m m(i,j)背包容量为j,可选择物品为i,i+1,...,n时背包的最优值 */ public static void knapsack(int[] value, int[] weight, int c, int[][] m){ int n = value.length - 1; // 初始化:只选第n个物品的时候,背包容量范围的各个值的所选物品的最优值 int jMax = Math.min(weight[n], c); for (int j = 0; j <= jMax; j++) { m[n][j] = 0; } for (int j = weight[n]; j < c; j++) { m[n][j] = value[n]; } // 可选物品为i,i+1,...,n-1,背包容量范围各个值的所选物品的最优值 for (int i = n - 1; i > 0; i--) { jMax = Math.min(weight[i], c); for (int j = 0; j < jMax; j++) { m[i][j] = m[i + 1][j]; } for (int j = weight[i]; j < c; j++) { m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - weight[i]] + value[i]); } } // 可选物品为1,2,...,n,背包容量为c的所选物品的最优值 m[0][c] = m[1][c]; if(c > weight[0]){ m[0][c] = Math.max(m[0][c], m[1][c - weight[0]] + value[0]); } } /** * 获取最优解 * @param m * @param weight * @param c * @param x */ public static void traceback(int[][] m, int[] weight, int c, int[] x){ int n = weight.length - 1; for (int i = 0; i < n; i++) { if(m[i][c] < m[i + 1][c]){ x[i] = 0; }else{ x[i] = 1; c -= weight[i]; } } x[n] = m[n][c] > 0 ? 1: 0; } /** * @param args */ public static void main(String[] args) { int c = 10; int[] weight = {5, 5, 5}; int[] value = {10,5,11}; int[][] m = new int[weight.length][c + 1]; knapsack(value, weight, c, m); int[] x={0,0,0}; traceback(m, weight, c, x); System.out.println("最优值为:" + m[0][c]); System.out.print("最优解为:"); for (int i = 0; i < x.length; i++) { System.out.print(x[i] + ((i != x.length - 1)? ",":"")); } System.out.println(" "); System.out.println("最优值矩阵为:"); for (int i = 0; i < weight.length; i++) { for (int j = 0; j < c + 1; j++) { System.out.print(m[i][j] + ((j != c) ? "," :"")); } System.out.print(" "); } } }
结果为:
最优值为:21
最优解为:1,1,0
最优值矩阵为:
0,0,0,0,0,0,0,0,0,0,21
0,0,0,0,0,11,11,11,11,11,0
0,0,0,0,0,11,11,11,11,11,0