536 字
3 分钟
代码随想录算法训练营第三十二天 | 动态规划 Part05
🎒 完全背包问题
- 问题描述:给定物品重量和价值,背包容量为
n
,每个物品可以选多次,求在容量不超过限制下的最大价值。 - 状态定义:
dp[i][j]
表示前i
个物品中,容量不超过j
的最大总价值。 - 状态转移方程:
- 不选第
i
个物品:dp[i][j] = dp[i - 1][j]
- 选第
i
个物品:dp[i][j] = dp[i][j - weight[i]] + value[i]
(前提j >= weight[i]
)
- 不选第
- 遍历顺序:外层遍历物品,内层遍历容量(正序)。
🔍 和 0-1 背包的区别
- 0-1 背包:每个物品最多选一次,容量遍历一般反向(倒序)。
- 完全背包:每个物品可选无限次,容量遍历一般正序。
卡码网:52.携带研究材料
import sysinput = sys.stdin.read
def main(): data = input().strip().split() n = int(data[0]) v = int(data[1])
dp = [0] * (v + 1)
index = 2 for _ in range(n): w = int(data[index]) val = int(data[index + 1]) index += 2
if w > v: continue
# 完全背包,容量正序遍历 for j in range(w, v + 1): dp[j] = max(dp[j], dp[j - w] + val)
print(dp[v])
main()
518. 零钱兑换 II
class Solution: def change(self, amount: int, coins: List[int]) -> int: n = len(coins) dp = [[0] * (amount + 1) for _ in range(n + 1)] # 金额为0时,只有一种组合方式——什么都不选 for i in range(n + 1): dp[i][0] = 1
for i in range(1, n + 1): for j in range(1, amount + 1): if j - coins[i - 1] >= 0: # 选择不使用当前硬币 + 选择使用当前硬币 dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i - 1]] else: dp[i][j] = dp[i - 1][j] return dp[n][amount]
🔢 377. 组合总和 IV
LeetCode 377. Combination Sum IV
class Solution: def combinationSum4(self, nums: List[int], target: int) -> int: dp = [0] * (target + 1) dp[0] = 1 # 目标为0时,组合数为1(空组合)
for t in range(1, target + 1): for num in nums: if t - num >= 0: dp[t] += dp[t - num]
return dp[target]
🏃 卡码网:57.爬楼梯
import sysinput = sys.stdin.read
def climb_stairs(n, m): dp = [0] * (n + 1) dp[0] = 1 for i in range(1, n + 1): for k in range(1, m + 1): if i - k >= 0: dp[i] += dp[i - k] return dp[n]
def main(): data = input().strip().split() n = int(data[0]) m = int(data[1]) print(climb_stairs(n, m))
main()
代码随想录算法训练营第三十二天 | 动态规划 Part05
https://fuwari.vercel.app/posts/code_musings_day_thirty-two/