本博客笔记内容来源于灵神,视频链接如下:https://www.bilibili.com/video/BV16Y411v7Y6?vd_source=7414087e971fef9431117e44d8ba61a7\&spm_id_from=333.788.player.switch
01背包
计算了f[i+1],f[i]就没用了,相当于每时每刻只有两个数组在参与运算:
494题是求方案数的,要初始化成 0。
如果是恰好型背包并且要计算最大最小,那么初始值就和 inf 有关。
力扣494题:

对于至少/至多的变形问题,变形类似:


完全背包
力扣322题:

其中:从二维递推式来理解,
例如01背包,更新f【c】的值需要的是当前f【c】和上一个状态的f【c-w】,因为我们现在之后一个数组,若是正序,f【c-w】就更新过了,也就不是上一个状态的值了,所以必须逆序 ;
若是完全背包,更新f【c】的值需要的是当前f【c】和当前状态的f【c-w】,需要的就是更新过的值,所以正序是没问题的。

python
class Solution:
def lengthOfLongestSubsequence(self, nums: List[int], target: int) -> int:
# 先使用递归
# 恰好等于target ==背包容量
# 长度即选物品,其价值为1
# 只能选一次:01背包问题
n = len(nums)
# 1.递归:
@cache
def dfs(i,c):
if i<0:
return 0 if c==0 else -inf
if c< nums[i]:
return dfs(i-1,c)
return max(dfs(i-1,c),dfs(i-1,c-nums[i])+1)
ans= dfs(n-1,target)
dfs.cache_clear()
return ans if ans>-1 else -1
# 2. 转为递推:
dp[i+1][c]= max(dp[i][c],dp[i][c-nums[i]]+1) 整体加了1
dp =[[-inf]*(target+1) for _ in range(n+1)]
dp[0][0]=0
for i,x in enumerate(nums):
for c in range(target+1):
if c<x:
dp[i+1][c]=dp[i][c]
else:
dp[i+1][c]= max(dp[i][c],dp[i][c-x]+1)
ans = dp[n][target]
return ans if ans>-1 else -1
# 3. 进一步优化为滚动数组
dp =[[-inf]*(target+1) for _ in range(2)]
dp[0][0]=0
for i,x in enumerate(nums):
for c in range(target+1):
if c<x:
dp[(i+1)%2][c]=dp[i%2][c]
else:
dp[(i+1)%2][c]= max(dp[i%2][c],dp[i%2][c-x]+1)
ans = dp[n%2][target] # 记得这里也要%2
return ans if ans>-1 else -1
# 4. 进一步优化为1维滚动数组
dp =[-inf]*(target+1)
dp[0]=0
for x in nums:
for c in range(target,x-1,-1):
if c<x:
dp[c] = dp[c]
else:
dp[c]= max(dp[c],dp[c-x]+1)
ans = dp[target]
return ans if ans>-1 else -1