/**
* 动态规划_0-1背包问题
* @author Matt
*/
public class Knapsack {
/**
* 求得最优值
* @param v 物品价值数组
* @param w 物品质量数组
* @param c 背包容量
* @param m 最优值数组
*/
public static void knapsack(int []v, int []w, int c, int [][]m) {
int n = v.length - 1;
int jMax = Math.min(w[n]-1, c);
for (int j = 0; j <= jMax; j++) {
m[n][j] = 0;
}
for (int j = w[n]; j <= c; j++) {
m[n][j] = v[n];
}
for (int i = n - 1; i > 1; i--) {
jMax = Math.min(w[i]-1, c);
for (int j = 0; j <= jMax; j++) {
m[i][j] = m[i+1][j];
}
for (int j = w[i]; j <= c; j++) {
m[i][j] = Math.max(m[i+1][j], m[i+1][j-w[i]] + v[i]);
}
m[1][c] = m[2][c];
if (c >= w[1]) {
m[1][c] = Math.max(m[1][c], m[2][c-w[1]] + v[1]);
}
}
}
/**
* 最优解路径
* @param m 最优值数组
* @param w 质量数组
* @param c 背包容量
* @param x 是否拿取数组
*/
public static void traceback(int [][]m, int []w, int c, int []x) {
int n = w.length - 1;
for (int i = 1; i < n; i++) {
if (m[i][c] == m[i+1][c]) x[i] = 0;
else {
x[i] = 1;
c -= w[i];
}
x[n] = (m[n][c] > 0) ? 1 : 0;
}
}
public static void main(String[] args) {
int []v = {0, 6, 3, 5, 4, 6};
int []w = {0, 2, 2, 6, 5, 4};
int c = 10;
int [][]m = new int[7][11];
int []x = new int[7];
knapsack(v, w, c, m);
traceback(m, w, c, x);
System.out.println("Value: " + m[1][c]);
System.out.print("Trace: ");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i]);
}
}
}