背包问题的核心公式

把每个背包问题的核心代码放在一块,更好的区分不同问题的代码实现。当然,在实现代码之前,要先了解每个背包问题解决问题的思路。

物品的重量数组是 weight (int[]),价值数组是 value (int[]),背包容量是 bagWeight

1. 0-1 背包

从大到小遍历,为了保证每个物品仅被添加一次

1.1 使用二维数组存储

递推公式

dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
(dp[i][j]:放入物品和不放入物品,哪个值大)

dp 大小

int[weight.size()][bagWeight+1][物品个数][背包容量+1]

代码

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) {
    for(int j = bagWeight; j >= 0; j--) {
        if (j < weight[i]) dp[i][j] = dp[i-1][j]
        else dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])
    }
}
1.2 使用一维数组存储

递推公式

dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
( dp[j]:放入物品和不放入物品,哪个值大)

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

2. 完全背包

完全背包的物品是可以添加多次的,所以要从小到大去遍历

2.1 组合

递推公式

dp[j] = max(dp[j], dp[j-nums[i]]) ( dp[j]:由 dp[1], dp[2], ... dp[j-1] 而来)

递推公式根据实际情况有所变化,通过找寻 dp[j] 是怎么通过其他的 dp 值推导而确定公式

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历物品,再遍历背包
for (int i = 0; i < weight.size(); i++) {
    for(int j = weight[i]; j < bagWeight ; j++) {
        dp[j] = max(dp[j], dp[j-weight[i]]+value[i])
    }
}
2.2 排列

递推公式

dp[j] = dp[j-nums[i]] ( dp[j]:由 dp[1], dp[2] ... dp[j-1] 而来)

递推公式根据实际情况有所变化,通过找寻 dp[j] 是怎么通过其他的 dp 值推导而确定公式

dp 大小

int[bagWeight+1][背包容量+1]

代码

// 先遍历背包,再遍历物品
for(int j = 0; j <= bagWeight; j++) { 
    for(int i = 0; i < weight.size(); i++) { 
        if (j >= wieght[i]) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

witheredwood
10 声望0 粉丝

引用和评论

0 条评论