动态规划法
核心思路
这个函数采用动态规划的思想,通过构建一个 ways 数组来累积计算每个金额对应的方法数。
逐行解析
1. 初始化
coins = [1, 2, 5, 10, 20, 50, 100, 200]
ways = [1] + [0] * 200 # 结果是 [1, 0, 0, 0, ..., 0] (共201个元素)
coins: 所有可用的硬币面值(单位:便士)ways[i]: 表示凑成金额i的方法数- 关键点:
ways[0] = 1表示凑成0元有1种方法(什么都不用),这是动态规划的基准条件
2. 双重循环的核心逻辑
for coin in coins: # 按顺序遍历每种硬币
for i in range(coin, 201): # 从当前硬币面值遍历到200
ways[i] += ways[i - coin]
这就是状态转移方程,其含义是:
凑成金额
i的方法数 = 原来方法数 + 使用当前硬币的方法数
其中 ways[i - coin] 表示:在使用了1枚当前硬币后,凑齐剩余金额的方法数。
具体执行过程演示
让我们跟踪计算前几个值的变化,以理解算法如何工作:
初始状态
ways = [1, 0, 0, 0, 0, 0, ...] # ways[0]=1
第1轮:使用硬币 1p
for i in range(1, 201):
ways[i] += ways[i-1]
i=1:ways[1] += ways[0]→0 + 1 = 1✓ 凑1p: {1}i=2:ways[2] += ways[1]→0 + 1 = 1✓ 凑2p: {1,1}i=3:ways[3] += ways[2]→0 + 1 = 1✓ 凑3p: {1,1,1}- ...
- 结果:只用1p硬币,每个金额都有且仅有1种方法
第2轮:加入硬币 2p
for i in range(2, 201):
ways[i] += ways[i-2]
关键更新点:
i=2:ways[2] += ways[0]→1 + 1 = 2- 原来:{1,1}
- 新增:{2}
i=3:ways[3] += ways[1]→1 + 1 = 2- 原来:{1,1,1}
- 新增:{1,2}
i=4:ways[4] += ways[2]→1 + 2 = 3- 原来:{1,1,1,1}
- 新增:{1,1,2}, {2,2}
第3轮:加入硬币 5p
当加入5p硬币后,凑5p的方法从1种 {1,1,1,1,1} 变成2种,新增 {5}。
以此类推,直到处理完所有硬币类型。
为什么这样计算?
这个算法的精妙之处在于:
-
按硬币顺序处理:确保计算的是组合数(不考虑顺序)
- {1,2,2} 和 {2,1,2} 视为同一种方法
- 如果调换循环顺序(先金额后硬币),会计算出排列数
-
累积效应:
ways数组保存的是所有已处理硬币能凑成的方法总数 -
避免重复:每种硬币只被考虑一次在其对应的外层循环中,确保不重复计算
关于动态规划
一、动态规划的数学原理
动态规划(DP)是求解多阶段决策优化问题的数学方法,其理论基础建立在贝尔曼最优性原理和函数方程之上。
1.1 核心理论框架
最优性原理(Principle of Optimality)
- 由Richard Bellman(1957)系统提出
- 形式化表述:若
P^*是问题I的最优策略,则其子策略P^*_k对于子问题I_k也是最优的 - 数学表达:
\text{opt}(n+1) = \max\{\text{opt}(j-1) + \text{end}(j, n+1)\}
Bellman方程 动态规划的核心是建立递推关系(状态转移方程):
v_x^n = \sup_{y \in X}(G_{xy} + v_y^{n-1})
其中 v_x^n 表示状态 x 在剩余 n 步时的最优价值函数,G_{xy} 为转移收益。
1.2 三大基本性质
- 最优子结构:问题的最优解包含子问题的最优解
- 重叠子问题:递归过程中多次计算相同子问题
- 无后效性(马尔可夫性):未来状态只与当前状态有关,与历史路径无关
1.3 数学分类
| 类型 | 数学特征 | 典型应用 |
|---|---|---|
| 确定性DP | 状态转移确定 | 背包问题、LCS |
| 随机DP(MDP) | 状态转移由概率分布决定 | 强化学习、金融决策 |
| 连续时间DP | Hamilton-Jacobi-Bellman方程 | 最优控制理论 |
| 离散时间DP | 差分Bellman方程 | 算法设计 |
二、严格验证的权威文献
核心原始著作
1. Richard Bellman (1957). Dynamic Programming. Princeton University Press.
- ISBN: 978-0-691-14668-3
- 验证信息:这是动态规划的奠基性著作。普林斯顿大学出版社官网可查,2010年重印版带有Stuart Dreyfus的新序言。在arXiv上超过100篇论文引用。
- 内容:系统提出最优性原理,建立离散时间动态规划的数学框架,是必读经典。
2. Martin L. Puterman (1994). Markov Decision Processes: Discrete Stochastic Dynamic Programming. Wiley.
- ISBN: 0-471-61977-9
- 验证信息:Wiley出版社官网明确收录,亚马逊等各大书店均有销售。在强化学习和运筹学领域被引用超过5000次。
- 内容:随机动态规划的权威教材,涵盖折扣、平均奖励等准则,是MDP领域的"圣经"。
现代权威教材
3. Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). Introduction to Algorithms (3rd ed.). MIT Press.
- ISBN: 978-0-262-03384-8
- 验证信息:MIT Press官网可查,ACM Digital Library收录。全球超过1000所大学采用,引用数超过73,000次。
- 内容:第15章"动态规划"提供完整理论框架和经典实例(矩阵链乘法、LCS、最优二叉搜索树)。
4. Kleinberg, J., & Tardos, É. (2006). Algorithm Design. Addison-Wesley.
- ISBN: 978-0-321-29535-4
- 验证信息:Addison-Wesley(Pearson旗下)官方出版,ACM Digital Library收录,全球Top 50 CS院校广泛使用。
- 内容:第6章专讲动态规划,强调设计范式而非算法罗列,包含加权区间调度、RNA二级结构等实例。
5. Dimitri P. Bertsekas. Dynamic Programming and Optimal Control (Vols. I & II, 4th ed., 2017/2012). Athena Scientific.
- ISBN Vol I: 978-1-886529-43-4
- ISBN Vol II: 978-1-886529-44-1
- 验证信息:Athena Scientific出版社官网明确,MIT等高校课程采用。是控制理论和最优控制领域的标准教材。
- 内容:涵盖确定性/随机系统、连续/离散时间、近似动态规划,数学深度极高。
实用算法手册
6. Skiena, S. S. (2020). The Algorithm Design Manual (3rd ed.). Springer.
- ISBN: 978-3-030-54255-9
- 验证信息:Springer官网可查,Stony Brook University课程采用,包含大量实战案例和War Story。
- 内容:第8章讲动态规划,强调问题识别和建模技巧,附有在线算法库。
三、辅助验证文献
历史经典
| 作者 | 著作 | 验证状态 | 核心贡献 |
|---|---|---|---|
| Howard (1960) | Dynamic Programming and Markov Processes | MIT Technology Press出版,交叉验证 | 策略迭代算法 |
| Dreyfus & Law (1977) | The Art and Theory of Dynamic Programming | 学术图书馆藏可查 | 计算复杂性分析 |
现代进阶
-
Bertsekas & Tsitsiklis (1996). Neuro-Dynamic Programming. Athena Scientific.
- 将DP与神经网络结合,是深度强化学习的数学基础
-
Sutton & Barto (2018). Reinforcement Learning: An Introduction (2nd ed.). MIT Press.
- ISBN: 978-0-262-03924-6
- 强化学习标准教材,DP在MDP中的完整应用
四、学习路径建议
初学者(算法竞赛/面试)
- Cormen《算法导论》第15章 → 建立理论基础
- Skiena《算法设计手册》 → 掌握问题识别
- 刷LeetCode DP分类题 → 实践巩固
进阶者(研究/工程)
- Bellman原著 → 理解数学本质
- Kleinberg & Tardos → 学习设计范式
- Bertsekas Vol I → 深化最优控制理论
专家(理论研究者)
- Puterman MDP → 随机环境DP
- Bertsekas Vol II → 近似DP
- 跟踪arXiv cs.AI/DS最新论文
五、关键数学公式总结
标准DP递推:
dp[i] = \begin{cases}
\max\{dp[j] + f(j,i)\}, & \text{优化问题} \\
\min\{dp[j] + f(j,i)\}, & \text{最小化问题} \\
\sum dp[j] \times g(j,i), & \text{计数问题}
\end{cases}
Bellman最优算子 (压缩映射):
(Tv)(s) = \max_{a \in A}\{r(s,a) + \gamma \sum_{s'}P(s'|s,a)v(s')\}