背包问题的核心公式
把每个背包问题的核心代码放在一块,更好的区分不同问题的代码实现。当然,在实现代码之前,要先了解每个背包问题解决问题的思路。
物品的重量数组是 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]);
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。