动态规划入门-01背包-状态转移方程的简单构造思想
动态规划入门——状态转移方程的简单构造思想
动态规划,往往是作为DFS的最终优化方案,由DFS的递归公式 到 状态转移方程
动态规划的题目一般是给出一组数据,每组数据都对应一个最终的解,我们需要选择出最优的一个解
怎么在过程中确定选择哪组数组才能得到最优解呢?
可以构造一个或多个状态转移方程来对解的构造进行设计
- 确定当前枚举到的方案能不能作为可选的方案(可选性)
- 确定这个数据能不能作为我们最优解的一部分(最优子结构)
- 最优解的转移(状态转移方程)
以一道经典的题目为例:
枚举每个物品,再枚举背包容量
for (int i = 1;i <= n;i++) for (int j = 0;j <= v;j++)
-
当前背包装不装的下第 \(i\) 个物品?
-
如果装得下,要不要装它?
可以写出
f[i][j] = f[i - 1][j];//不装 if (j >= cost[i]) f[i][j] = max(f[i][j], f[i - 1][j - cost[i]] + w[i]);//比较装和不装
其中,装第 \(i\) 件物品的总价值可以由不装第 \(i\) 件物品的价值加上第 \(i\) 件物品的价值推得
为什么要这样曲线救国地写呢?
因为我们在之前就已经将 f[i - 1][j - cost[i]]
算出来了!所以只需要进行一次计算就能求得当前的总价值,这也是动态规划的核心——状态转移方程,写出数学形式有:
\(F_{i,j}=max(F_{i-1,j},F_{i-1,j-cost_i}),j\ge cost_i\)
空间优化:观察上述的状态转移方程,可以发现当前的f[i][j]
只会和 f[i-1][j]
有关,可以自我覆盖更新最优解
得出以下公式:
for (int i = 1;i <= n;i++) for (int j = v;j >= cost[i];j--) f[j] = max(f[j], f[j - cost[i]] + w[i]);
这里需要倒序枚举j
背包容量,因为f[j - cost[i]]
需要用到<j
的值,在当前层时,上一层的j-cost[i]
已经全部计算出来了
也就是说不能使用已经覆盖过的值参与对下一个需要用到没有覆盖的值进行计算
这就是01背包的最终优化方案
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具