动态规划法学习

当然,让我们用更生活化的语言和一个实际的例子来解释动态规划,以及如何在实践中应用它。

动态规划通俗理解

想象一下,你是个水果摊老板,每天要决定订购多少苹果,目标是最大化利润。但苹果的价格每天波动,顾客的需求也变化,你该怎么办?

传统做法:每天早上,你都根据昨天的经验和今天的感觉猜测需求,然后订购苹果。但如果猜错,要么苹果卖不完亏本,要么不够卖错过赚钱机会。

动态规划做法:你开始记录每一天的销售数据,包括苹果价格、天气、节假日等因素。第二天,你不再凭感觉,而是根据历史数据预测需求,再决定订购量。因为你"记得"过去的经验,所以可以做出更精准的决策,减少浪费,增加利润。

实践过程详解

以经典的背包问题为例,假设你是个旅行者,背包容量有限,你要从一堆物品中选择装入背包,每件物品有重量和价值,你的目标是让背包里物品的总价值最大,但不超过背包容量。

步骤1:定义问题
  • 状态:背包当前的剩余容量,已经选了哪些物品。
  • 目标:背包内物品价值最大化。
步骤2:构建状态转移方程
  • 假设 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前i件物品装入容量为j的背包中的最大价值。
  • 状态转移方程为: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w e i g h t [ i ] ] + v a l u e [ i ] ) dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]) dp[i][j]=max(dp[i−1][j],dp[i−1][j−weight[i]]+value[i]),其中 w e i g h t [ i ] weight[i] weight[i]和 v a l u e [ i ] value[i] value[i]分别是第i件物品的重量和价值。
状态定义

我们定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示考虑前 i i i个物品,且背包容量为 j j j时,所能达到的最大价值。

状态转移方程

状态转移方程是这样的:

d p [ i ] [ j ] = max ⁡ ( d p [ i − 1 ] [ j ] , d p [ 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−wi]+vi)

这里:

  • d p [ i − 1 ] [ j ] dp[i-1][j] dp[i−1][j] 表示不拿第 i i i个物品,此时最大价值就是前 i − 1 i-1 i−1个物品在容量为 j j j的背包下的最大价值。
  • d p [ i − 1 ] [ j − w i ] + v i dp[i-1][j-w_i] + v_i dp[i−1][j−wi]+vi表示拿了第 i i i个物品,此时背包剩余容量为 j − w i j-w_i j−wi( w i w_i wi是第$ 个物品的重量),然后加上第 个物品的重量),然后加上第 个物品的重量),然后加上第i$个物品的价值 v i v_i vi 。
方程解读

这个方程意味着我们在考虑第 i i i个物品时,有两种选择:

  1. 不拿第 i i i个物品 :此时最大价值取决于前 i − 1 i-1 i−1个物品在容量为 j j j的背包下能达到的最大价值,即 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i−1][j]。
  2. 拿第 i i i个物品 :此时我们需要确保背包容量足够装下这个物品,即 j > = w i j >= w_i j>=wi。在这种情况下,我们的最大价值由前 i − 1 i-1 i−1个物品在剩余容量 j − w i j-w_i j−wi下的最大价值加上第 i i i个物品的价值组成,即 d p [ i − 1 ] [ j − w i ] + v i dp[i-1][j-w_i] + v_i dp[i−1][j−wi]+vi。

最终,我们取这两种选择中价值更大的那个作为 d p [ i ] [ j ] dp[i][j] dp[i][j]的值。

步骤3:初始化边界条件
  • 当背包容量为0或没有物品时,价值为0,即 d p [ 0 ] [ j ] = 0 dp[0][j] = 0 dp[0][j]=0和 d p [ i ] [ 0 ] = 0 dp[i][0] = 0 dp[i][0]=0。
步骤4:计算
  • 从 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0]开始,按行或列递增地填充整个二维数组,直到得到 d p [ n ] [ W ] dp[n][W] dp[n][W],即为所求的最大价值。
实践注意点
  1. 状态定义要准确:状态必须包含足够的信息来描述问题,但又不能过于复杂,否则计算量会很大。
  2. 避免重复计算:动态规划的核心是记忆化,即保存已计算的状态,避免重复计算相同的子问题。
  3. 边界条件:正确的边界条件是关键,否则可能导致整个解法失效。
  4. 空间优化:有时可以通过观察状态转移方程,仅保留必要的状态信息,减少内存消耗。

结语

动态规划就像一个智慧的决策者,它通过分析过去的"经验"(子问题的解),来做出更好的"未来决策"(解决大问题)。在实践中,清晰的状态定义、有效的状态转移方程和合理的边界条件是成功应用动态规划的关键。希望这次解释能帮助你更好地理解和掌握动态规划!

相关推荐
Dream_Snowar10 分钟前
速通Python 第四节——函数
开发语言·python·算法
Altair澳汰尔23 分钟前
数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者
人工智能·算法·机器学习·数据分析·知识图谱
A懿轩A1 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
Python机器学习AI1 小时前
分类模型的预测概率解读:3D概率分布可视化的直观呈现
算法·机器学习·分类
吕小明么2 小时前
OpenAI o3 “震撼” 发布后回归技术本身的审视与进一步思考
人工智能·深度学习·算法·aigc·agi
1 9 J2 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
程序员shen1616112 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
汝即来归2 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法
咒法师无翅鱼3 小时前
【定理证明工具调研】Coq, Isabelle and Lean.
算法
风清云淡_A3 小时前
【java基础系列】实现数字的首位交换算法
java·算法