0-1 背包问题
题目链接:0-1 背包问题
思路
- dp[i][j]的含义,即放入i个物品最大重量为j的最大价值。
- 初始化,注意第一行的值。
- 如果当前的重量大于最大重量,即前一个放入物品的最大价值为当前值
- 反之就是比较,-1就是与少一件的进行比较。
二维解法
weight=[1,3,4]
values=[15,20,30]
bag_size=4
dp=[[0]*(bag_size+1) for _ in range(len(weight))]
for i in range(1,bag_size+1):
if weight[0]<=i:
dp[0][i]=values[0]
for i in range(1,len(weight)):#遍历物品
cur_weight,cur_value=weight[i],values[i]
for j in range(1,bag_size+1):#重量
if cur_weight>j:
dp[i][j]=dp[i-1][j]
else:
#dp[i-1][j]表示不放入物品
dp[i][j]=max(dp[i-1][j],dp[i-1][j-cur_weight]+cur_value)
一维解法
weight = [1, 3, 4]
value = [15, 20, 30]
bag_weight = 4
# 初始化: 全为0
dp = [0] * (bag_weight + 1)
# 先遍历物品, 再遍历背包容量
for i in range(len(weight)):
for j in range(bag_weight, weight[i] - 1, -1):
# 递归公式
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
for j in range(bag_weight, weight[i] - 1, -1) ,表示已经放入了多少重量的物品。
需要仔细理解。
416. 分割等和子集
题目链接:416. 分割等和子集
这题抽象成0-1背包问题,就是有没有使得背包价值为sum/2的。
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
Sum=sum(nums)
if Sum%2==1:
return False
target=Sum/2
dp=[0]*(target+1)
for i in range(len(nums)):
for j in range(target,nums[i]-1,-1):
dp[j]=max(dp[j],dp[j - nums[i]] + nums[i])
if dp[j]==target:
return True
return False