前言
观看闫神的背包九讲的一点点笔记
代码实现
01背包的二维实现
// 外层循环是可以选择物品
for(int i=1; i<=n; i++){
// 内层循环时背包的容量
for(int v=w[i]; v<=V;v++){
/*
dp[i][v]表示前i个元素总容量为v时最大的价值
对于第i个元素只有两种选择:选or不选,
如果选最大价值就是dp[i-1][v-w[i]] + c[i],不选则为dp[i-1][v]
*/
dp[i][v] = max(dp[i-1][v], dp[i-1][v-w[i]] + c[i]);
}
}
01背包的一维实现
二维中主要的关系式为:dp[i][v] = max(dp[i-1][v], dp[i-1][v-w[i]] + c[i])
即第i层的,主要由i-1层来决定。
// 第i行的状态只与第i-1行的状态有关
for(int i=1; i<=n; i++){
// 这里修改为逆序的, 这样保证v-w[i]一定是上一层的状态: 因为v-w[i]肯定小于v,现在是从大的v到小的v,所以可以保证v-w[i]在v之前没有被更新过
for(int v=V; v>=w[i]; v--){
dp[v] = max(dp[v], dp[v-w[i]]+c[i]);
}
}
完全背包的一维实现
和01背包的一维实现的区别仅仅在于内层循环从逆序变为了顺序
for(int i=1; i<=n; i++){
// 这里修改为顺序的
for(int j=w[i]; j<=V; j--){
dp[j] = max(dp[j], dp[j-v[i]]+c[i]);
}
}
初始化问题(一维数组)
- 当dp中的所有元素都初始化为0时候,dp[v]表示的为背包容量小于等于v时的最大容量。
- 只有dp[0]初始化为0,其余都初始化为负无穷,此时dp[v]表示的为背包容量等于v时的最大容量
求方案数(以01背包为例)
plan[i]表示容量为i时的方案数,注意,plan[0]=1,因为容量为0时,什么都不选就是一种方案
for(int i=1; i<=n; i++){
for(int v=V; v>=w[i]; v--){
t = max(dp[v], dp[v-w[i]]+c[i]);
s = 0
// 转移到当前状态的方案数,可能两个方案都可以转
if t == dp[v] s += plan[v]
if t == dp[v-w[i]] s += plan[v-w[i]]
plan[v] = s
dp[v] = t
}
}
背包方案数例题
518. 零钱兑换 II - 完全背包求方案数
根据上面求方案数,再直接套上完全完全背包的模板即可
class Solution:
def change(self, amount: int, coins) -> int:
dp = [float("-inf")] * (amount+1)
plan = [0] * (amount+1)
dp[0] = 0
# 什么都不取就是一种方案
plan[0] = 1
for i in range(len(coins)):
for j in range(coins[i], amount+1):
t = max(dp[j], dp[j-coins[i]]+coins[i])
s = 0
if t == dp[j]:
s += plan[j]
if t == dp[j-coins[i]]+coins[i]:
s += plan[j-coins[i]]
plan[j] = s
dp[j] = t
return plan[amount]
377. 组合总和 Ⅳ - 完全背包求方案书数变体
这一题和上面一题非常相似,但是完全背包求方案数,对于相同数字的不同组合只算作一种方案。这里每一种排序都是一种新方案,唯一的改动就是交换内外层循环,即外层循环为背包容量,内层循环为选取的元素。
class Solution:
def combinationSum4(self, nums, target) -> int:
plan = [0] * (target+1)
dp = [float("-inf")] * (target+1)
dp[0], plan[0] = 0, 1
# 对于可以不同顺序可以看作不同方案的
# 外循环为总容量,内循环为nums。和01、完全背包是相反的
for v in range(1, target+1):
for i in range(len(nums)):
if v >= nums[i]:
t = max(dp[v], dp[v-nums[i]]+nums[i])
s = 0
if t == dp[v]:
s += plan[v]
if t == dp[v-nums[i]]+nums[i]:
s += plan[v-nums[i]]
plan[v] = s
dp[v] = t
return plan[-1]