当前位置: 首页 > news >正文

代码随想录第32天:动态规划5(组合、排列、最小方法数)

一、零钱兑换(Leetcode 518)

1、确定dp数组以及下标的含义

使用 下标为[0, i]的coins[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种组合方法。

2、确定递推公式

dp[i][j] = dp[i - 1][j] + dp[i][j - nums[i]]

3. dp数组初始化

dp[i][0] 的含义:用物品i(即coins[i]) 装满容量为0的背包 有几种组合方法。

都有一种方法,即不装。dp[i][0] 都初始化为1

dp[0][j]的含义:用「物品0」(即coins[0]) 装满 背包容量为j的背包,有几种组合方法。如果 j 可以整除 物品0,那么装满背包就有1种组合方法。

4. 确定遍历顺序

二维DP数组的完全背包的两个for循环先后顺序都可以。

class Solution:def change(self, amount: int, coins: List[int]) -> int:n = len(coins)dp = [[0] * (amount + 1) for _ in range(n + 1)]dp[0][0] = 1  # 0个硬币凑出金额0的方法是1种for i in range(1, n + 1):  # 遍历硬币种类for j in range(amount + 1):  # 遍历目标金额# 不选当前硬币 coins[i-1]dp[i][j] = dp[i - 1][j]# 选当前硬币(只要j >= coins[i-1])if j >= coins[i - 1]:dp[i][j] += dp[i][j - coins[i - 1]]return dp[n][amount]

一维数组解法:

1、确定dp数组以及下标的含义

dp[j]:凑成总金额j的货币组合数为dp[j]

2、确定递推公式

dp[j] += dp[j - coins[i]]

3. dp数组初始化

装满背包容量为0 的方法是1,即不放任何物品,dp[0] = 1

4. 确定遍历顺序

先物品再背包求的是组合数,先背包后物品求的是排列数!!!

求组合所以本题先物品后背包

from typing import Listclass Solution:def change(self, amount: int, coins: List[int]) -> int:# 初始化一维数组 dp,长度为 amount + 1# dp[j] 表示凑出金额 j 的组合数dp = [0] * (amount + 1)# 凑出金额为 0 只有一种方式:什么也不选dp[0] = 1# 遍历每一个硬币for coin in coins:# 遍历金额从 coin 到 amount# 只从 coin 开始是因为凑不出比硬币面额更小的金额for j in range(coin, amount + 1):# 状态转移:凑出金额 j 的方法数 += 凑出金额 j - coin 的方法数dp[j] += dp[j - coin]# 返回凑出目标金额 amount 的组合方式数return dp[amount]

二、组合总合IV(Leetcode 377)

1、确定dp数组以及下标的含义

dp[i]:凑成目标正整数为i的排列个数为dp[i]

2、确定递推公式

dp[i] += dp[i - nums[j]]

3. dp数组初始化

dp[0] = 1

4. 确定遍历顺序

先物品再背包求的是组合数,先背包后物品求的是排列数!!!

求排列所以本题先背包后物品

from typing import Listclass Solution:def combinationSum4(self, nums: List[int], target: int) -> int:# dp[i] 表示凑出和为 i 的排列个数(顺序不同算不同的组合)dp = [0] * (target + 1)# 凑出和为 0 只有一种方式:什么也不选dp[0] = 1# 从 1 到 target 遍历每一个目标值 ifor i in range(1, target + 1):# 遍历每一个数字 num,尝试使用它来构造 ifor j in range(len(nums)):if i >= nums[j]:# 如果当前目标值 i ≥ num,则可以从 i - num 的方案转移过来dp[i] += dp[i - nums[j]]# 最终结果是凑出目标和 target 的所有排列数return dp[target]

三、爬楼梯(Kamacoder 57)

1、确定dp数组以及下标的含义

dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法。

2、确定递推公式

dp[i]有几种来源,dp[i - 1],dp[i - 2],dp[i - 3] 等等,即:dp[i - j],递推公式为:dp[i] += dp[i - j]

3. dp数组初始化

dp[0] = 1

4. 确定遍历顺序

先物品再背包求的是组合数,先背包后物品求的是排列数!!!

求排列所以本题先背包后物品

def solve(n, m):dp = [0] * (n + 1)dp[0] = 1for j in range(1, n + 1):for i in range(1, m + 1):if j >= i:dp[j] += dp[j - i]return dp[n]if __name__ == '__main__':n, m = list(map(int, input().split(' ')))print(solve(n, m))

四、零钱兑换(Leetcode 322)

1、确定dp数组以及下标的含义

dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

2、确定递推公式

凑足总额为 j - coins[i] 的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j]

所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。

递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

3. dp数组初始化

dp[0] = 0

dp[j]应该初始化为一个最大的数float('inf'),这样在min(dp[j - coins[i]] + 1, dp[j])比较的过程中保持更新

所以下标非0的元素都初始化为最大值float('inf')。

4. 确定遍历顺序

先物品再背包求的是组合数,先背包后物品求的是排列数!!!

本题并不强调集合是组合还是排列,习惯先物品后背包

from typing import Listclass Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 初始化 dp 数组,长度为 amount + 1,初始值为正无穷(代表初始无法到达)# dp[i] 表示凑出金额 i 所需的最少硬币数dp = [float('inf')] * (amount + 1)# 凑出金额 0 所需的硬币数为 0dp[0] = 0# 遍历每一种硬币for coin in coins:# 对每一个从 coin 到 amount 的金额 j 进行遍历for j in range(coin, amount + 1):# 状态转移方程:如果 j - coin 可以被凑出# 则 j 也可以被凑出,其所需硬币数为 dp[j - coin] + 1dp[j] = min(dp[j], dp[j - coin] + 1)# 如果最终凑不出 amount 金额,返回 -1;否则返回最小硬币数return dp[amount] if dp[amount] != float('inf') else -1

相关文章:

  • 强化学习ppo算法在大语言模型上跑通
  • 迭代器模式
  • python计算shp中每个区域的面积
  • 语音合成之十一 提升TTS语音合成效果:低质量数据清洗、增强与数据扩增
  • 判断字符是否唯一 --- 位运算
  • C++ 外观模式详解
  • Guass数据库实验(数据字典设计、交叉表设计)
  • linux种文件名usr的含义是什么?
  • 20250505解压缩tar.xz压缩包的方法
  • Allegro23.1新功能之自动添加器件下方相邻层禁布操作指导
  • Adobe LiveCycle Designer
  • Android控件VideoView用法
  • DeepSeek-能力边界
  • 数据库的并发控制
  • USB资料摘录for后期,bus hound使用
  • 小白学习java第16天(下):javaweb
  • 凸性(Convexity)
  • Python小酷库系列:bidict,可以双向查询的dict
  • 2025年5月5日星期一的摸鱼大冒险
  • 音视频作品:AI生成音乐、短视频的邻接权保护
  • 3477亿美元!伯克希尔一季度现金储备再创新高,担忧关税战不确定性影响
  • 美国证实加拿大及墨西哥汽车零部件免关税
  • 微博:严厉打击对肖某董某事件蹭炒热点、编造故事博流量等行为
  • 网商银行2024年年报发布,客户资产管理规模超过1万亿
  • 住房和城乡建设部办公厅主任李晓龙已任部总工程师
  • 专访|200余起诉讼,特朗普上台100天,美国已进入宪政危机