坚持按题型打卡&刷&梳理力扣算法题系列,语言为python3,Day5
- 0-1背包【目标和】
- 有n个物品,第i个物品的体积为w[i], 价值为v[i]。每个物品至多选一个,求体积和不超过capacity时的最大价值和
- 常见变形
- 至多装capacity,求方案数/最大价值和(max)
- 恰好装capacity,求方案数/最大/最小价值和(+)
- 至少装capacity,求方案数/最小价值和(min)
- 完全背包【零钱兑换】
- 有 n 种物品,第 i 种物品的体积为w[i], 价值为v[i]。每种物品无限次重复选,求体积和不超过capacity时的最大价值和
- 🌟与0-1背包回溯的区别:
- 在选了一个物品之后,i 是不变的,表示可以继续选第 i 种物品
目标和
- 题目描述
- 代码参考
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
target += sum(nums)
if target < 0 or target % 2:
return 0
target //= 2 # //和等号之间不能留空格
n = len(nums)
@cache
def dfs(i,c):
if i < 0: # 当前的物品取完了
return 1 if c==0 else 0 # 判断结果是否合法
if c < nums[i]: # 勿漏!!如果当前剩余容量c小于nums[i], 则直接return 不选
return dfs(i-1,c)
return dfs(i-1,c) + dfs(i-1,c-nums[i]) # 否则return两者(不选 选)相加
return dfs(n-1,target)
零钱兑换
- 题目描述
-
Tips
- 首先拿到数组长度
- 然后定义dfs函数
- 先写边界条件,注意判断合法情况
- 再判断c(背包容量)够不够减,不够的话就直接return不选
- return max/+/min 不选 选
-
代码参考
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
n = len(coins)
@cache
def dfs(i,c): #此处dfs返回值代表的是硬币个数
if i < 0:
return 0 if c==0 else inf # 当所有种类物品取完的时候,判断是否合法,inf代表无穷大
if c < coins[i]:
return dfs(i-1,c)
return min(dfs(i-1,c),dfs(i,c-coins[i])+1)
ans = dfs(n-1,amount)
return ans if ans < inf else -1