每天学一个算法--动态规划(Dynamic Programming, DP)

📘 教案 04:动态规划(Dynamic Programming, DP)


1. 问题定义

动态规划用于解决一类问题:

最优子结构 + 重叠子问题

典型目标:

  • 求最小值 / 最大值
  • 求方案数
  • 求可行性

2. 核心思想

动态规划的本质:

将复杂问题分解为子问题,并保存子问题结果,避免重复计算


3. 核心术语(必须讲清)


3.1 最优子结构(Optimal Substructure)

定义:

一个问题的最优解可以由其子问题的最优解构成


例子:

最短路径:

$[

dist(A \to C) = dist(A \to B) + dist(B \to C)

]


3.2 重叠子问题(Overlapping Subproblems)

定义:

子问题会被多次重复计算


例子(斐波那契):

text 复制代码
f(n) = f(n-1) + f(n-2)

会重复计算:

text 复制代码
f(n-2), f(n-3), ...

3.3 状态(State)

定义:

描述子问题的变量


示例:

dp\[i\]=前 i 个元素的最优解\]\[ dp\[i\] = \\text{前 i 个元素的最优解} \]\[dp\[i\]=前 i 个元素的最优解


3.4 状态转移(State Transition)

定义:

从子问题推导当前问题的关系


示例:

dp\[i\]=dp\[i−1\]+dp\[i−2\]\]\[ dp\[i\] = dp\[i-1\] + dp\[i-2\] \]\[dp\[i\]=dp\[i−1\]+dp\[i−2\]


3.5 边界条件(Base Case)

定义:

最小子问题的初始值


4. DP 的本质(核心理解)


动态规划不是"算法技巧",而是:

建立状态 + 建立转移方程


5. DP 与递归的关系


递归:

  • 自顶向下
  • 会重复计算

DP:

  • 自底向上
  • 记录结果(避免重复)

6. DP 基本步骤(必须背)


Step 1:定义状态

dp\[i\]=?\]\[ dp\[i\] = ? \]\[dp\[i\]=?


Step 2:写转移方程

dp\[i\]=f(dp\[...\])\]\[ dp\[i\] = f(dp\[...\]) \]\[dp\[i\]=f(dp\[...\])


Step 3:确定初始值


Step 4:计算顺序


7. 示例1:斐波那契(入门)


定义:

text 复制代码
f(n) = f(n-1) + f(n-2)

DP写法:

text 复制代码
dp[0] = 0
dp[1] = 1

for i = 2 to n:
    dp[i] = dp[i-1] + dp[i-2]

时间复杂度:

O(n)\]\[ O(n) \]\[O(n)


8. 示例2:爬楼梯(核心模型)


问题:

每次可以走 1 或 2 步,问有多少种走法


状态定义:

dp\[i\]=走到第 i 阶的方法数\]\[ dp\[i\] = \\text{走到第 i 阶的方法数} \]\[dp\[i\]=走到第 i 阶的方法数


转移:

dp\[i\]=dp\[i−1\]+dp\[i−2\]\]\[ dp\[i\] = dp\[i-1\] + dp\[i-2\] \]\[dp\[i\]=dp\[i−1\]+dp\[i−2\]


本质:

👉 这是"组合问题"


9. 示例3:背包问题(必须讲)


0-1背包

给定:

  • 重量 (w[i])
  • 价值 (v[i])
  • 容量 (W)

状态:

dp\[i\]\[j\]=前 i 个物品,容量 j 的最大价值\]\[ dp\[i\]\[j\] = \\text{前 i 个物品,容量 j 的最大价值} \]\[dp\[i\]\[j\]=前 i 个物品,容量 j 的最大价值


转移:

dp\[i\]\[j\]=max⁡(dp\[i−1\]\[j\],dp\[i−1\]\[j−w\[i\]\]+v\[i\])\]\[ dp\[i\]\[j\] = \\max( dp\[i-1\]\[j\], dp\[i-1\]\[j-w\[i\]\] + v\[i\] ) \]\[dp\[i\]\[j\]=max(dp\[i−1\]\[j\],dp\[i−1\]\[j−w\[i\]\]+v\[i\])


含义:

  • 不选第 i 个物品
  • 选第 i 个物品

10. 时间复杂度


取决于状态数量:

O(状态数×转移成本)\]\[ O(\\text{状态数} × \\text{转移成本}) \]\[O(状态数×转移成本)


11. 空间优化(进阶)


从二维到一维

text 复制代码
for i:
    for j = W down to w[i]:
        dp[j] = max(dp[j], dp[j-w[i]] + v[i])

为什么倒序?

防止重复使用同一物品


12. DP 的分类(重要)


类型 特点
线性DP 一维
区间DP 区间转移
背包DP 容量限制
树形DP 树结构
状态压缩DP 位运算

13. 常见错误(教学重点)


❌ 错误1:不会定义状态

👉 状态必须"完整描述子问题"


❌ 错误2:转移方程写错

👉 本质是"决策枚举"


❌ 错误3:顺序错

👉 会导致使用未计算值


❌ 错误4:边界条件遗漏


14. DP 与贪心区别


项目 DP 贪心
是否全局最优 ❌(不一定)
是否回溯
复杂度

15. 关键结论


  1. DP = 状态 + 转移
  2. 本质是"避免重复计算"
  3. 适用于最优问题
  4. 设计难点在建模
相关推荐
水木流年追梦2 小时前
CodeTop 热门题目汇总hot300题
算法·leetcode·职场和发展
小糖学代码2 小时前
LLM系列:2.pytorch入门:3.基本优化思想与最小二乘法
人工智能·python·算法·机器学习·ai·数据挖掘·最小二乘法
爱写代码的倒霉蛋2 小时前
天梯赛备赛经验分享(基础版)
经验分享·算法
f3iiish2 小时前
2078. 两栋颜色不同且距离最远的房子 力扣
算法·leetcode
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【排序贪心】:拼数
c++·算法·贪心·csp·信奥赛·排序贪心·拼数
炽烈小老头3 小时前
【 每天学习一点算法 2026/04/21】螺旋矩阵
学习·算法
未来转换3 小时前
基于A2A协议的生产应用实践指南(Java)
java·开发语言·算法·agent
谭欣辰3 小时前
AC自动机:多模式匹配的高效利器
数据结构·c++·算法
joker_sxj3 小时前
论文阅读-DeepSeek-mHC
论文阅读·算法