今天的主要的目的是理解0-1背包问题.dp[i][j]代表到物品i位置,容量j能最多装多少价值的东西.那么递推公式就是dp[i][j]=max(dp[i-1][j], dp[i-1][j-weight[i]+value[i]) 前者表示不放物品i的情况,后者表示放物品i的情况
416. Partition Equal Subset Sum
这道题是0-1背包的一道变种题,基本思路就是算dp[-1][-1]==sum(nums).
Way1:
地推公式的变化在于如果nums[i]比当前的j值大,是肯定不能放入的,反之则是常规的递推公式.
初始化上首先全都置0. 其次对于dp[i][0]来说应该也是0因为所有的num都会大于0. 对于dp[0][j]来说,就需要进行比较.比较的方法就是如果当前的j大于nums[0]那么就置成nums[0]
除此之外还需要开始和最后的比较.开始的比较是要判断sum是不是个偶数,还有一个就是最后的值是否能等于sum//2
class Solution:
def canPartition(self, nums: List[int]) -> bool:
target=sum(nums)
nums.sort()
if target%2==1:
return False
target=target//2
dp=[[0 for _ in range(target+1)] for _ in range(len(nums))]
for i in range(len(nums)):
dp[i][0]=0
for j in range(1,target):
if nums[0]<=j:
dp[0][j]=nums[0]
for i in range(1,len(nums)):
for j in range(1,target+1):
if nums[i]<=j:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])
else:
dp[i][j]=dp[i-1][j]
return dp[-1][target]==target
Way2:
这种方法更加的巧妙.直接把dp置成true & false,基本思路不变
class Solution(object):
def canPartition(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
s=sum(nums)//2
if sum(nums)%2==1:
return False
l=len(nums)
dp = [[False for _ in range(s+1)] for _ in range(l+1)]
for i in range(l+1):
dp[i][0]=True
for i in range(1,l+1):
for t in range(1,s+1):
if nums[i-1] <= t:
dp[i][t]=dp[i-1][t] or dp[i-1][t-nums[i-1]]
else:
dp[i][t]=dp[i-1][t]
return dp[l-1][s]