Skip to content

第六章 综合练习

设计原则

本章练习遵循教材设计哲学(参考 Ch1/Ch2/Ch5):

  • 问题驱动:不只是"计算复杂度",而是"为什么这样设计"
  • 展示推理:不只给答案,还要展示思考过程
  • 多样化:包括反例、变式、边界条件、开放设计
  • 无固定三层:避免机械模仿,推动真正的理解

一、问题情境与直觉建立

1. 为什么 Fibonacci 递归这么慢?

用具体例子说明:fib(5) 的调用树,哪些节点被重复计算?

2. 最优子结构的直觉

为什么最短路径有最优子结构,最长简单路径没有?用剪贴证明解释。

3. 状态设计的权衡

状态维度越多越好吗?分析维度与空间的权衡。

4. 可插拔框架的威力

为什么一个 DP 框架能解决一族问题?用编辑距离 vs LCS 说明。

5. KV-Cache 的本质

KV-Cache 和 DP 记忆化有什么共同条件?用 prefix reuse 解释。


二、方法应用与实现

6. Fibonacci 三阶实现

实现三种版本:

  • 朴素递归:O(φ^n)
  • 记忆化:O(n)
  • 空间优化:O(1)

对比运行时间(n=30, 40, 50)。

7. LCS 完整实现

实现 LCS,包括:

  • 基本版本:O(mn) 空间
  • 滚动数组:O(n) 空间
  • 路径重构:输出最长公共子序列

8. 钢条切割路径重构

实现钢条切割,输出最优切割方案(不只是收益)。

9. 矩阵链乘 Knuth 优化

对比普通版本 O(n³) 和 Knuth 优化版本 O(n²),测试 n=100。

10. KV-Cache 模拟

模拟 KV-Cache 的 prefix reuse:

  • 给定 5 个请求
  • 计算缓存复用率
  • 分析效率提升

三、错误诊断与反例

11. 子问题重叠误判

有人用 DP 优化 Quicksort,分析错误原因。

12. 最优子结构遗漏

最长简单路径用 DP,构造反例说明剪贴失败。

13. 状态维度错误

某问题设计了 5 维状态,空间爆炸,分析改进方案。

14. 初始化遗漏

编辑距离忘记初始化第一行/列,预测错误。

15. KV-Cache 失效场景

给定无 prefix reuse 的场景,分析 KV-Cache 失效原因。


四、方案比较与权衡

16. 记忆化 vs 迭代

对比两种 DP 实现方式:

  • 适用场景
  • 实现难度
  • 空间/时间复杂度

17. 滚动数组 vs 状态压缩

对比两种空间优化技术:

  • 适用条件
  • 效果对比
  • 实现难度

18. 编辑距离 vs LCS

对比两个问题的框架差异:

  • 桩函数差异
  • 递推式差异
  • 复杂度差异

19. DP vs 贪心

对比两种策略:

  • 适用条件(最优子结构 + 贪心选择性质)
  • 反例构造
  • 复杂度差异

20. KV-Cache vs 无缓存

对比两种推理策略:

  • 条件差异
  • 效率差异
  • 空间权衡

五、变式与边界条件

21. Tribonacci(三阶 Fibonacci)

定义:T(n) = T(n-1) + T(n-2) + T(n-3)

设计状态,实现 DP,空间优化。

22. 带权 LCS

字符有权重,求权重之和最大的 LCS。设计状态和递推式。

23. 最长公共子串

必须是连续的,设计状态(与 LCS 不同)。

24. TSP 状态爆炸

分析 TSP 的状态空间大小(n=10, 20, 30),讨论为什么 O(n² × 2^n) 仍比暴力好。

25. Token 依赖非 DAG

如果 LLM 的 attention 是双向的(非因果),KV-Cache 策略需如何调整?


六、开放设计

26. 新问题判断

给定问题(如"汉诺塔"),判断:

  • 是否有子问题重叠?
  • 是否有最优子结构?
  • 是否适合用 DP?

27. DP 识别器设计

设计一个 Agent:

  • 输入:问题描述
  • 输出:是否适合 DP + 状态设计建议

28. 桩函数创新

为"最长公共子串"设计可插拔框架的桩函数。

29. KV-Cache 管理策略

设计动态 KV-Cache 管理策略:

  • 缓存哪些 token?
  • 何时丢弃?
  • 类比 DP 的滚动数组

30. LLM 推理优化

设计 LLM 推理优化方案:

  • Prefix reuse 检测
  • Batch 推理组合
  • 复杂度分析

七、综合应用

31. 课程安排问题

用 DP 解决实际问题:安排课程表(避免时间冲突),设计状态。

32. 最优股票买卖

用 DP 解决:最多 k 次交易的最优收益,设计状态(三维)。

33. 排课 Agent

设计一个排课 Agent,组合 DP(小规模精确)+ 启发式(大规模近似)。

34. 真实 LCS

用 LCS 解决实际问题:基因序列比对,对比不同变体(带权、子串)。

35. 综合挑战

选择一个 NP-hard 问题(如 SAT),设计求解器:

  • 小规模:DP 或回溯
  • 大规模:启发式
  • 分析复杂度

八、思考题

36. 为什么 DP 需要两个条件?

子问题重叠和最优子结构,为什么都是必要?缺一个会怎样?

37. 如何判断问题适合 DP?

三步判断法:

  1. 是否有子问题重叠?
  2. 是否有最优子结构?
  3. 状态空间是否有限?

38. 框架思维的价值?

可插拔框架为什么比单独实现更强大?迁移能力在哪?

39. DP 与 LLM 的本质连接?

为什么理解 DP 能帮助理解 KV-Cache?人的判断在哪?

40. 搜索策略的演进路径?

从贪心到 GoT:贪心 → DP → ToT → GoT。分析每一步的改进。


九、LLM 协同实验

41. 递推式生成

让 LLM 为新问题(如"书本分页")生成 DP 递推式,你验证最优子结构。

42. 桩函数设计

让 LLM 扩展编辑距离框架支持新变体(如"最长公共子串"),你评判桩函数设计。

43. KV-Cache 策略

让 LLM 设计 KV-Cache 管理策略,你分析 prefix reuse 条件。

44. 故障诊断

给定错误的 DP 实现(状态定义错误),让 LLM 找 bug,你验证。

45. 综合挑战

用 LLM 协同解决 TSP(小规模 n≤15):

  • LLM 生成状态设计
  • 你实现并验证
  • 对比效率

附录:实验数据模板

Fibonacci 三版本对比

n朴素递归时间记忆化时间空间优化时间
30
40
50

LCS 空间优化对比

m=n基本版本空间滚动数组空间效率倍数
100
1000
10000

矩阵链乘 Knuth 优化

n普通版本时间Knuth 优化时间效率倍数
10
50
100

KV-Cache 效率分析

场景无缓存时间有缓存时间Prefix reuse 率
5 个请求,共享前缀
5 个请求,无共享

实验指导

如何记录推理收据?

每次与 LLM 协作解决 DP 问题时,记录:

  1. 问题描述:清晰的问题陈述
  2. 状态设计过程
    • LLM 建议:...
    • 你的质疑:...
    • 最终方案:...
  3. 最优子结构验证:剪贴证明过程
  4. 实现与测试:代码和测试结果
  5. 反思
    • LLM 的建议哪些正确?
    • 哪些需要你修正?
    • 人的判断在哪?

如何分析 Prefix Reuse 率?

给定一组 LLM 推理请求,分析:

  1. 统计每个请求的 token 数
  2. 找共享前缀(最长公共前缀)
  3. 计算 reuse token 数
  4. 计算复用率:reuse token 数 / 总 token 数
  5. 分析 KV-Cache 效率提升

学习目标自检

完成练习后,应能回答:

  • 识别子问题重叠:给定递归问题,判断是否适合 DP 优化
  • 验证最优子结构:用剪贴证明判断 DP 正确性
  • 设计状态空间:从一维到多维,平衡维度与效率
  • 实现记忆化与迭代:两种方式,理解优劣
  • 连接 LLM 推理:理解 KV-Cache 与 DP 记忆化的同构性

写在最后:动态规划最难的不是"记住递推公式",而是识别问题结构。练习的目标是让你面对新题时,知道从哪里开始想。


参考文献

  • Cormen T H, et al. Introduction to Algorithms[M]. 4th ed. MIT Press, 2022. Chapter 15.
  • Skiena S S. The Algorithm Design Manual[M]. 3rd ed. Springer, 2020. Chapter 10.
  • Kleinberg J, Tardos E. Algorithm Design[M]. Pearson, 2005. Chapter 6.
  • Yao S, Yu D, Zhao J, et al. Tree of Thoughts[C]//NeurIPS. 2023.

新时代的算法课程