DP查缺补漏之01背包优化原理
1|0DP查缺补漏之01背包优化原理
先复习一下基本知识
- 状态假设
DP[I][J]
为前 个物品,容量小于 时的最优解(最大价值)
- 状态转移
DP[I][J] = max(DP[I - 1][J], DP[I - 1][J - V[I]] + W[I])
- 对于第
个物品,两种可能- 装入背包
- 则状态应通过前
个物品,容量小于 时的最优解再加上W[I]
转移,但是实际上本次状态的容量才为 ,若直接从DP[I-1][J]
转移则忽略了该物品体积,所以应从减去该次物品体积的DP[I - 1][J - V[I]]
转移。即DP[I - 1][J - V[I]] + W[I]
- 证明此解严谨性
- 上一层循环已然计算了
DP[I - 1][0 ~ M]
的所有最优解 - 则
DP[I - 1][J - V[I]]
已经是最优解
- 上一层循环已然计算了
- 则状态应通过前
- 不装入背包
- 则状态应通过前
个物品,容量小于 时的最优解直接进行转移
- 则状态应通过前
- 装入背包
- 对于第
- 代码处理
- 开二维数组来对标状态假设
- 初始化
DP[0][0~M]
为 - 两层循环递推,外层枚举
,内层枚举 - 进行
DP[I][J] = DP[I - 1][J - V[I]] + W[I]
状态转移时必须确保
优化思路(空间)
-
从状态转移方程入手
DP[I][J] = max(DP[I - 1][J], DP[I - 1][J - V[I]] + W[I])
- 每个
DP[I][J]
都是从DP[i-1][x]
转移而来 - 显然可以用滚动数组
- 每个
-
具体化优化思路
-
直接删除第一维
-
用循环来直接进行对上一维的转移
-
-
但这有一个问题,此时的
dp[j - w[i]]
实际上就是本次 的,因为是从小到大递推的,要操作每一个dp[i - 1][j]
的时候都已经被更新成此次状态的dp[i][j]
了,此时需要一个妙手,第二层循环反着枚举 -
-
因为所有大的都是由小的转移而来,由大至小的枚举使得每一次要取
dp[j-w[i]]
时,dp[j-w[i]]
都是 上一次循环的最优解,不会被更新。
-
-
__EOF__

本文作者:Kdlyh
本文链接:https://www.cnblogs.com/kdlyh/p/17802581.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/kdlyh/p/17802581.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下