1049. 最后一块石头的重量 II
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
summ = sum(stones)
target = summ//2
#dp下标和数组的定义,dp[j]代表的是最大价值
dp = [0]*15001
#递归公式
for i in range(len(stones)):
for j in range(target,stones[i]-1,-1):
#包括i,不包括i
dp[j] = max(dp[j],dp[j-stones[i]]+stones[i])
return summ - dp[target]-dp[target]
为什么会想到01背包也是一件很棘手的问题。
因为summ//2是向下取整,所以,summ-dp[target]一定比dp[target]大
代码随想录
494. 目标和
整个背包全部用加法运算的话,总和为sum
部分用加分符号的话:x(正数的集合)
其它减法符号:sum-x(负数的集合)
我们要求x - (sum-x) = target
转化一下: x = (target+sum)/2
就像找两个集合,正数的集合和负数的集合
递推公式的推导也挺抽象的,dp[j]代表容量为j,有dp[j]种方法
已有物品为1,在dp[4]种方法的基础上凑成dp[5]
已有物品2,dp[3]种方法的基础上凑成dp[5]。。。
可以推出公式dp[j] += dp[j-nums[i]
初始化:
dp[0] = 1
为了让后面的数都不会等于0,使用临界条件判断
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
#dp[j]的含义:容量为j的时候有dp[j]种方法
summ = sum(nums)
#没有方案的时候
if abs(target) > summ:
return 0
if (target+summ)%2 == 1:
return 0
want = (target+summ)//2
#初始化
dp = [0]*(want+1)
dp[0] = 1
#遍历顺序
for i in range(len(nums)):
for j in range(want,nums[i]-1,-1):
#递归公式
dp[j] += dp[j-nums[i]]
#打印dp数组
return dp[want]
大家重点理解 递推公式:dp[j] += dp[j - nums[i]],这个公式后面的提问 我们还会用到。
代码随想录
474.一和零
通过这道题目,大家先粗略了解, 01背包,完全背包,多重背包的区别,不过不用细扣,因为后面 对于 完全背包,多重背包 还有单独讲解。
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
#dp数组的含义,dp[i][j]指的是有i个0,j个1的背包,最大能装多少个物品
dp = [[0]*(n+1)for _ in range(m+1)]
#初始化
dp[0][0] = 0
#遍历顺序
x = 0
y = 0
#遍历物品
for str in strs:
#统计有多少个0,多少个1
one = str.count('1')
zero = str.count('0')
#遍历背包
for i in range(m,zero-1,-1):
for j in range(n,one-1,-1):
dp[i][j] = max(dp[i][j],dp[i-zero][j-one]+1)
#递归公式
return dp[m][n]
#打印
代码随想录