用二维dp数组dp[i][j],dp[i][j]表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少
//初始化 初始化dp[0][j]和 dp[i][0](为0 默认)
//dp[0][j]
for(int j = weight[0];j<=bagweight;j++) {
dp[0][j] = value[0];
}
for(int i = 1;i<weight.length;i++) {
for(int j = 1;j<=bagweight;j++) { //遍历顺利 先物品或者先重量都可以
if(j<weight[i]) { //放不下物品i
dp[i][j] = dp[i-1][j];
} else { //放的下,考虑是否要放
//放物品i或者不放,取最大的
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
}
}
}
dp[weight.length-1][bagweight]
压缩,用一维数组dp[j]。dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j],那么dp[0]就应该是0,因为背包容量为0所背的物品的最大价值就是0。
初始化:
dp数组在推导的时候一定是取价值最大的数,如果题目给的价值都是正整数那么非0下标都初始化为0就可以了。
这样才能让dp数组在递归公式的过程中取的最大的价值,而不是被初始值覆盖了。
那么我假设物品价值都是大于0的,所以dp数组初始化的时候,都初始为0就可以了。
一维dp数组遍历顺序:
倒序,保证物品i只被放入一次,背包容量从大到小遍历; 需要先遍历物品再遍历重量
for(int i = 0;i<weight.length;i++) { //先遍历物品再遍历背包(重量)
for(int j = bagweight;j>=weight[i];j--) {
dp[j] = Math.max(dp[j], dp[j-weight[i]]+value[i]);
}
}
dp[bagweight]
dp[j] = d[j-nums[i]];
//比如已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包