Skip to content

什么是动态规划(DP)?

动态规划是一种“记住过去,优化现在”的算法技巧,适合用来解决那些可以拆成重复子问题的最优方案问题。

你可以把它理解成:“有记忆能力的递归” —— 每个结果都记录下来,避免重复劳动。

1. 线性 DP(Linear DP)

特点:

  • 状态沿着一维数组或序列线性推进
  • 当前状态只依赖前面若干固定状态(如前一项、前两项)
  • 常见于爬楼梯、路径最小和、子数组最大和等问题

举例:走楼梯,每一步只能走一格或两格

你要爬一个楼梯,每次可以走 1 步或 2 步。你会思考:我从第 n-1 层走上来的?还是从 n-2 层跳上来的?这就构成了一个线性的递推关系。

适用场景:

  • 一维方向上推进(如数组、楼梯、房屋、路径)
  • 每个状态只与前面若干个状态有关

对应题目:

2. 0-1 背包(0-1 Knapsack)

特点:

  • 每个物品只能选一次
  • 状态是:在前 i 件物品中,如何使得总重量 ≤ 背包容量,并让价值最大

举例:背行李旅行,每件东西只能带一次,行李有重量限制

你准备出国旅行,行李箱最多只能装 20kg。你面前有很多物品,每样都有重量和价值。你只能选择带或不带(不能带两件),怎么装最值?

适用场景:

  • 是否可以选出一部分数,刚好满足一个目标值
  • 如何从一堆值里选出一部分,最大化某个指标

对应题目:

3. 完全背包(Complete Knapsack)

特点:

  • 每个物品可以选无限次
  • 状态是:在前 i 种物品中,如何组合成目标数值

举例:用硬币换零钱,每种硬币你有无限枚

假如你要凑出 10 块钱,你有无限枚 1元、2元、5元的硬币,有多少种换法?

适用场景:

  • 硬币兑换、组合总数、无限资源配比问题

对应题目:

4. 子序列类 DP(Subsequence DP)

特点:

  • 不要求连续,只要顺序保持即可
  • 用于比较“两个序列的相似度”或“找出某种趋势”

举例:在一句话里找出关键词组成句子的可能性

比如你听了一段长对话,现在想回忆是否说过“hello”,你只需要检查是否有 h、e、l、l、o 按顺序出现,不用连续。

适用场景:

  • 最长公共子序列
  • 最长递增子序列
  • 编辑距离(修改多少次能变成另一个字符串)

对应题目:

5. 区间 DP(Interval DP)

特点:

  • 处理一个范围内的子问题(通常是 [i...j])
  • 适合分割、合并、爆破类问题

举例:切蛋糕,想知道切的顺序对总成本有多大影响

蛋糕太大,要切成小块带走。每次切的代价是这块蛋糕当前的长度。你切的顺序不同,总花费可能差很多。你想知道最优切法。

适用场景:

  • 石头合并
  • 气球戳破
  • 多段合并、拆分

对应题目:

6. 状态压缩 DP(Bitmask DP)

特点:

  • 用二进制的每一位代表“一个选择是否被用过”
  • 适用于组合数量爆炸时的优化

举例:组队出任务,用 01 表示谁上场

有 10 个队员,你要选出部分人上战场,每人只能上一次。你用二进制表示选择状态,比如 10101 表示 1、3、5号被选中。

适用场景:

  • 所有子集枚举
  • 所有人都走一遍(旅行商问题)

对应题目:

7. 数位 DP(Digit DP)

特点:

  • 用来统计数字组成、数字出现次数等问题
  • 按位枚举每一位可能的取值,带上限制和记忆化

举例:你想数一下从 1 到 10000 中出现了多少次“1”

你数着数着发现重复工作太多了,于是你决定按位统计(比如个位、十位、百位...)一次性搞定。

适用场景:

  • 某个数字在区间 [1, n] 中出现的次数
  • 满足某些规则的数字个数

对应题目:

8. 树形 DP(Tree DP)

特点:

  • 用 DFS 在树结构上传递信息(通常是从叶子往上)
  • 每个节点的状态依赖于子树的状态

举例:年终奖金发放,规定上司和下属不能同时领奖

公司里是树形结构,领导发奖金时担心上下级勾结,所以一旦某个员工领奖,他的直属上级就不能领。怎样发奖金总额最大?

适用场景:

  • 树上路径、分配、选取问题
  • 祖孙关系下的选择冲突

对应题目:

9. 状态机 DP(State Machine DP)

特点:

  • 不同状态之间切换,有冷却期、手续费等限制
  • 常用于股票买卖场景

举例:你在炒股,不同天有不同规则:今天卖完要等明天再买

你只能同时持有一只股票;卖出后要休息一天才能再买;每次交易要交手续费……每天都在做最优选择。

适用场景:

  • 股票买卖最大收益
  • 状态有限(持有/不持有/冷却中)

对应题目:

10. 博弈型 DP(Game Theory DP)

特点:

  • 两人轮流选择,你必须在假设对方最聪明的前提下做最优选择
  • 通常是 Min-Max 类型的递归 + 记忆化

举例:两人玩取石子游戏,你拿一堆、我拿一堆,谁先取完赢

你们轮流拿石头,每次可以从左右两边选一个。你知道对方也会选得最聪明,那你自己应该从哪边拿才能确保胜利?

适用场景:

  • 玩家轮流操作、最大最小策略
  • 模拟两人博弈,判断先手是否稳赢

对应题目: