代码随想录算法训练营第37天 | 动态规划:背包问题
背包问题模版问题
https://kamacoder.com/problempage.php?pid=1046
背包问题二维——代码随想录
https://programmercarl.com/背包理论基础01背包-1.html
背包问题一维——代码随想录
https://programmercarl.com/背包理论基础01背包-2.html#算法公开课
416.分割等和子集
https://leetcode.cn/problems/partition-equal-subset-sum/submissions/548729942/
代码随想录
https://programmercarl.com/0416.分割等和子集.html#算法公开课
背包问题
分类
01 背包
变量:
物品件数:n
物品重量:w
物品[i]的重量:weight[i]
物品[i]的价值:value[i]
二维dp题解思路
- dp定义:dp[i][j] 代表第i个物品容量为j的最大价值
- dp初始化:物品0时,当小于物品0的容量时,价值为0,大于物品0容量时,价值为物品0;
- dp[i][j]递推公式:
- 最大容量能放下物品i时:
j-weight[i]>0 max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
python - 放不下时直接为上一个物品的容量
dp[i-1][j]
python
- 最大容量能放下物品i时:
- 遍历顺序:都在左上角;所以不用重复;
def bag_map(m,n,weight,value):
##初始化dp矩阵
dp = [[0]*(n+1) for _ in range(m)]
for i in range(n+1):
if i>=weight[0]:
dp[0][i] = value[0]
for i in range(1,m):
for j in range(1,(n+1)):
if j-weight[i]>=0:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
else:
dp[i][j] = dp[i-1][j]
return dp[-1][-1]
一维dp解题思路
- dp定义不变
- 初始化可以直接为0
- 每次都dp都为上一个物品的数据
- 遍历顺序改变:
- 重量从重向轻遍历;从轻向重遍历会给轻的物品重复放多次;
- 先遍历物品,再遍历重量;循环直接有依赖;
def bag_map(m,n,weight,value):
##初始化dp矩阵
dp = [0]*(n+1)
for i in range(0,m):
for j in range(n,-1,-1):
if j-weight[i]>=0:
dp[j] = max(dp[j],dp[j-weight[i]]+value[i])
return dp[-1]
416. 分割等和子集
题解思路
- nums[i]里的值既是value 也是weight
class Solution:
def canPartition(self, nums: List[int]) -> bool:
target = sum(nums)
if target%2==0:
target//=2
else:
return False
dp = [0]*(target+1)
for i in range(1,len(nums)):
for j in range(target,-1,-1):
if j>=nums[i]:
dp[j] = max(dp[j],dp[j-nums[i]]+nums[i])
if dp[j]==target:
return True
if dp[-1]==target:
return True
else:
return False