还不会动态规划?那就进来看看吧

动态规划:用“备忘录”征服复杂问题的“人生哲学”

相关系列文章链接:
《贪心算法 vs 动态规划:“急性子”算法能不能赢?》
《还不会动态规划?那就进来看看吧》
《八皇后、数独、背包问题:回溯算法如何成为算法世界的万能钥匙?》
《0-1背包难题哪家强:回溯法 VS 动态规划 VS 贪心算法》

引言:为什么程序员总爱写备忘录?

你有没有这种经历:面对一个复杂问题时,总想“要是能记住之前算过的结果就好了”?比如考试时,你发现今天的数学题和上周的题目思路一模一样,但你却不得不重新推导一遍——这简直像在玩“记忆障碍版俄罗斯方块”!动态规划(Dynamic Programming, DP)就是程序员的“终极备忘录”,它用空间换时间,把“重复造轮子”的痛苦变成“查表”这么简单。今天我们就来聊聊这个算法界的“记忆大师”——动态规划,以及它如何解决经典的0-1背包问题。


一、动态规划的基本思想:分而治之,但别“分崩离析”

1.1 什么是动态规划?

动态规划是一种通过分解问题保存中间结果来优化复杂问题的算法思想。它听起来很高大上,但其实原理很简单:把大问题拆成小问题,然后把小问题的答案记下来,避免重复计算

举个栗子:
假设你想计算斐波那契数列的第100项(F(100) = F(99)+F(98)),如果用递归直接算,你会发现程序会疯狂计算F(40)、F(39)这些重复的子问题,直到你的电脑热到能煎鸡蛋。而动态规划会说:“别急!我先把F(0)到F(100)的答案都存进一个表格,每次只需要查表,而不是重新计算!”

1.2 动态规划的“四大法宝”:

  1. 最优子结构:大问题的最优解由小问题的最优解组合而成。
    (比如,要选最优路线,每一步的选择也必须是最优的。)
  2. 重叠子问题:问题可以分解成许多重复的小问题。
    (比如,斐波那契数列里F(50)会被计算无数次!)
  3. 状态转移方程:用数学公式描述如何从子问题推导出大问题。
    (比如,F(n) = F(n-1) + F(n-2) 就是状态转移方程。)
  4. 备忘录/表格:保存已经解决的子问题的答案。
    (就像考试时偷偷带的小抄!)

1.3 动态规划 vs 分治算法:一个记笔记,一个忘性大

分治算法(比如快速排序、归并排序)虽然也会拆分问题,但它有个致命缺点——不保存中间结果。就像你考试时把笔记撕了,每次都要重新推导一遍。而动态规划就像一个强迫症患者,每算一步就记下来,绝不浪费脑细胞。


二、实战演练:0-1背包问题——“带有限额的购物车”

2.1 问题描述:穷游者的终极难题

假设你是个背包客,背着一个容量为W的背包去购物,面前有N件商品,每件商品有重量和价值。你只能选择“全拿”或“不拿”(0-1选择),目标是让背包里商品的总价值最大。
(比如:背包容量10kg,商品A重3kg价值5元,商品B重4kg价值6元,选哪个更划算?)

2.2 动态规划如何“装逼”?

步骤1:定义状态

用一个二维表格dp[i][j]表示:
前i件物品中,用容量为j的背包能装的最大价值
(比如dp[3][5]表示前3件物品,用容量5kg的背包能装的最大价值。)

步骤2:状态转移方程

对于第i件物品,有两种选择:

  • 不装:最大价值就是dp[i-1][j](继承前i-1件的结果)。
  • :前提是背包容量够!此时价值为物品价值 + dp[i-1][j - 物品重量]
    最终取两者的最大值:
    dp[i][j] = max( dp[i-1][j], value[i] + dp[i-1][j - weight[i]] )
步骤3:初始化表格
  • dp[0][j] = 0:0件物品时,无论背包多大,价值都是0。
  • dp[i][0] = 0:背包容量为0时,装什么都不行。
步骤4:填表大法

从上到下、从左到右填满表格,最终dp[N][W]就是答案!


2.3 举个栗子:价值与重量的“生死时速”

假设:

  • 物品列表:
    物品 重量 价值
    A 1 1
    B 3 4
    C 4 5
    D 5 7
  • 背包容量:W=7kg
填表过程:
  1. 初始化表格
    dp[0][...] = 0,第一行全为0。
  2. 逐行计算
    • 物品A(重量1,价值1)
      对于j从1到7,dp[1][j] = max(不装A的价值0,装A的价值1)
      所以dp[1][1~7]全为1。
    • 物品B(重量3,价值4)
      当j<3时,装不下B,所以dp[2][j] = dp[1][j]
      当j>=3时,比较装B(价值4 + dp[1][j-3])和不装B(dp[1][j])。例如:
      dp[2][3] = max(1, 4+0)=4
      dp[2][4] = max(1,4+1)=5
    • 继续计算物品C、D,最终表格最后一行(第4行)的dp[4][7]就是答案。
最终结果:

通过表格计算,你会发现最大价值是7+1=8(选D和A)或者5+4=9?哦不!等等!这里需要仔细计算,但表格会告诉你正确答案是9(比如选B+C)。
(具体填表过程建议自己动手试一试,表格会告诉你真相!)


三、动态规划的“人生哲学”

3.1 动态规划的三大优点:

  1. 效率高:避免重复计算,把指数级复杂度降到多项式级。
  2. 思路清晰:把大问题拆解成小问题,一步步解决。
  3. 万能钥匙:适用于路径规划、资源分配、字符串匹配等几乎所有优化问题。

3.2 动态规划的局限性:

  • 空间消耗大:需要保存整个表格,可能占用内存。
  • 问题需满足条件:必须有最优子结构和重叠子问题,否则动态规划就是“杀鸡用牛刀”。

四、总结:动态规划的“通关秘籍”

动态规划就像一位精明的理财师,通过记录每一步的“最优选择”,最终帮你找到全局最优解。它的核心思想可以用一句话概括:
“别重复造轮子,把每一步的智慧都写进备忘录!”

下次当你面对复杂问题时,不妨试试动态规划的思路:

  1. 把问题拆解成小问题。
  2. 用表格记录每一步的结果。
  3. 用数学公式描述如何从子问题推导出大问题。

现在,你已经掌握了算法界的“记忆大师”——动态规划。快去征服那些让你头疼的背包、路径、字符串问题吧!毕竟,人生就像一个超大的0-1背包,而动态规划就是帮你找到最优解的“人生指南”~

(本文部分内容参考自CSDN技术博客、哔哩哔哩教程等,感谢各位算法大神的无私分享!)

你可能感兴趣的:(算法,动态规划,算法)