**
思考:
**背包问题是一个经典的动态规划模型。它既简单形象容易理解,又在某种程度上能够揭示动态规划的本质,故不少教材都把它作为动态规划部分的第一道例题.
分析:
与零一背包不同的是,零一背包中的物品是不可以重复拿取的,只可以拿取当前物品或者不拿取当前物品,不可以拿取多个,完全背包的物品是可以任意拿取多个的来构成不超过背包容量并且构成的总价值是最大的.
而这道题是多重背包问题,也就是这个物品的个数是有限个的,在物品个数范围内可以任意选择。
动态规划的核心是找到dp公式或者状态转移的方程,理解清楚中间的过程是怎么样进行变化的,因为动态规划总是要利用到之前上一个物品选择后的最佳方案,所以dp数组里面存储的肯定是历史上存储的最佳方案,一开始的时候我们是可以借助excel表格来帮助我们理解dp数组是怎样生成的。
具体代码:
public static class MultiKnapsack {
private static int[] P={2,3,4};
private static int[] V={3,4,5};
private static int[] M={4,3,2};
private static int T = 15;
private int[] newResults = new int[T + 1];
@Test
public void resolve4() {
int result = ksp(P.length,T);
System.out.println(result);
}
private int ksp(int i, int t){
// 开始填表
for (int m = 0; m < i; m++){
// 考虑第m个物品
// 分两种情况
// 1: M[m] * V[m] > T 则可以当做完全背包问题来处理
if (M[m] * V[m] >= T) {
for (int n = V[m]; n <= t ; n++) {
newResults[n] = Math.max(newResults[n], newResults[n - V[m]] + P[m]);
}
} else {
// 2: M[m] * V[m] < T 则需要在 newResults[n-V[m]*k] + P[m] * k 中找到最大值,0 <= k <= M[m]
for (int n = V[m]; n <= t ; n++) {
int k = 1;
while (k < M[m] && n > V[m] * k ){
newResults[n] = Math.max(newResults[n], newResults[n - V[m] * k] + P[m] * k);
k++;
}
}
}
// 可以在这里输出中间结果
System.out.println(JSON.toJSONString(newResults));
}
return newResults[newResults.length - 1];
}
}