DP查缺补漏之完全背包优化原理

1|0DP查缺补漏之完全背包优化原理

1|0先复习一下基本知识

  • 状态假设

    • DP[I][J]为前i个物品,容量小于j时的最优解(最大价值)
  • 状态转移

    • DP[I][J] = max(DP[I - 1][J], DP[I - 1][J - k*V[I]] + k*W[I])
      • 对于第i个物品,两种可能
        • 装入背包(装入1Si(SiV[i]<=j)个)
    • 不装入背包
      • 则状态应通过前i1个物品,容量小于j时的最优解直接进行转移
  • 代码处理

    • for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { for (int k = 0; k * v[i] <= j; k++) { DP[i][j] = max(DP[i][j], DP[i - 1][j - v[i] * k] + w[i] * k); } } }

1|0优化思路(时间和空间)

  • 时间复杂度

    • 从状态方程分析

      • DP[I][J] = max(DP[I - 1][J], DP[I-1][J-V] + W, DP[I-1][J-2V] + 2W, ... , DP[I-1][J-NV] + NW)
      • DP[I][J-V] = MAX( DP[I-1][J-V], DP[I-1][J-2V] + 1W, ... , DP[I-1][J-NV] + (N-1)W)
        • 每一项都比DP[I][J]小一个W,最大值即DP[I][J-V]DP[I][J]相差一个W。
      • DP[I][J] = DP[I,J-V] + W
    • 用新转移方程实现

      • for (int i = 1; i <= n; i++) { for (int j = 0; j <= m; j++) { DP[i][j] = DP[i - 1][j]; if (j >= v[i]) DP[i][j] = max(DP[i][j], DP[i][j - v[i]] + w[i]); } }
      • 注意右边那项是DP[i][j - v[i]] + w[i],这与01背包不同

  • 空间复杂度

    • 从状态方程分析

      • DP[i][j] = max(DP[i][j], DP[i][j - v[i]] + w[i])
      • 仍然可以优化空间,但是与01不同的是这个方程并非滚动,本次的大答案只能由本次的小答案推出,所以第二层for应从小到大枚举
    • 代码实现

      • for (int i = 1; i <= n; i++) { for (int j = v[i]; j <= m; j++) { DP[j] = max(DP[j], DP[j - v[i]] + w[i]); } }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17803165.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示