0-1背包问题通常情况下物品的重量是整数的,采用动态规划可以解决,在解决物品重量非整数情况下的背包问题之前,我们先来回顾整数背包问题,并从中寻找解决非整数背包问题的方法。
问题定义:有n种物品和一个容量为c的背包,第i件物品的重量为wi,价格为vi,求出哪种物品组合放入背包使物品价值总和最大。
整数0-1背包问题
设p(i,j)表示在容量为j情况下,将物品i,i+1…n组合的放入背包的最优解的值
则其转移方程为
如果 j>=wi ,p(i,j) = max(p(i+1,j), p(i+1,j-wi )+vi )
如果 j<wi , p(i,j) = p(i+1,j)
可以理解为当j<wi ,背包无法放下第i件物品,所以其最优解和考虑放i+1到n的物品到容量为j的背包的最优解相同。当j>=wi 时,可以选择放和不放第i件物品,当不放时背包价值和p(i+1,j)相同,当放时背包价值为p(i+1,j-wi )再加上第i件物品的价值。
所以整数背包问题可以采用动态规划解决,开辟n*c的数组,从下往上不断更新数组的值,得到p(i,j)的值,最优解就是p(0,c)的值
public static int solution(int c, int[] v, int[] w){
if(v.length != w.length){
throw new IllegalArgumentException();
}
int n = v.length;int m = c+1;
int[][] result = new int[n][m];
for(int i = 0;i < m;i++){
result[n-1][i] = i>=w[n-1]? v[n-1]:0;
}
for(int i = n-2;i>=0;i--){
for(int j = 0;j < m;j++){
if(j < w[i]){
result[i][j] = result[i+1][j];
}else {
result[i][j] = Math.max(result[i+1][j], result[i+1][j-w[i]]+v[i]);
}
}
}
traceBack(c, v, w, result);
return result[0][c];
}
路径回溯ÿ