Day 37 | 01背包问题 、416. 分割等和子集
01背包问题 二维dp
https://programmercarl.com/背包理论基础01背包-1.html
视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6
有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
思考
dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
def test_2_wei_bag_problem1():
weight = [1, 3, 4]
value = [15, 20, 30]
bagweight = 4
# 二维数组
dp = [[0] * (bagweight + 1) for _ in range(len(weight))]
# 初始化
for j in range(weight[0], bagweight + 1):
dp[0][j] = value[0]
# weight数组的大小就是物品个数
for i in range(1, len(weight)): # 遍历物品
for j in range(bagweight + 1): # 遍历背包容量
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])
print(dp[len(weight) - 1][bagweight])
test_2_wei_bag_problem1()
01背包问题 一维dp
https://programmercarl.com/背包理论基础01背包-2.html
视频讲解:https://www.bilibili.com/video/BV1BU4y177kY
思考
在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。
思考
使用滚动数组,先物品再背包。背包遍历需要逆序,正序的话上一层的左侧值就被覆盖了,无法滚动。
def test_1_wei_bag_problem():
weight = [1, 3, 4]
value = [15, 20, 30]
bagWeight = 4
# 初始化
dp = [0] * (bagWeight + 1)
for i in range(len(weight)): # 遍历物品
for j in range(bagWeight, weight[i] - 1, -1): # 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
print(dp[bagWeight])
416. 分割等和子集
本题是 01背包的应用类题目
https://programmercarl.com/0416.分割等和子集.html
视频讲解:https://www.bilibili.com/video/BV1rt4y1N7jE
思考
暴力回溯太费事了。
转换为01背包问题。背包容量为sum/2,物品重量为nums[i],价值也是nums[i]
dp[i] 背包容量i是否可以装满
class Solution:
def canPartition(self, nums: List[int]) -> bool:
if len(nums)==1:
return False
sum_ = sum(nums)
if sum_ % 2 !=0:
return False
k = int(sum_ / 2)
# dp[i] 背包容量i是否可以装满
dp = [False] * (k+1)
dp[0] = True
for num in nums:
for i in range(k,0,-1):
if i>=num:
dp[i] = dp[i] or dp[i-num]
return dp[k]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步