<
01背包
>
上一篇

qwq
下一篇

动态规划

二维dp数组01背包

用二维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数组(滚动数组)

压缩,用一维数组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的背包
Top
Foot