【代码随想录刷题笔记】完全背包与01背包总结

背包问题总结
  1. 分类

    物品不重复 -> 01背包

    物品可重复 -> 完全背包

  2. 时间复杂度:O(m*n),m为物品个数,n为背包最大容量。

    空间复杂度:一维dp -> O(n),二维dp -> O(n*m)

  3. 应用

    • 能否装满背包 -> dp[j] = max(dp[j], dp[j - weight[i]] + values[i]),返回判断dp[target] == target?
    • 装满背包有几种方法 -> dp[j] += dp[j - weight[i]]
    • 背包装满最大价值 -> dp[j] = max(dp[j], dp[j - weight[i]] + values[i]),返回dp[target]
    • 装满背包所有物品的最小个数 -> dp[j] = min(dp[j - weight[i]] + 1,dp[j])
  4. 遍历顺序

    • 01背包二维dp:背包容量从小到大,for嵌套顺序随意。

    • 01背包一维dp:背包容量从大到小,必须先遍历物品,再嵌套遍历背包容量。

      以dp[j] = max(dp[j], dp[j - weight[i]] + values[i])为例:

      背包容量从大到小 -> 因为一维数组是二维的压缩,而dp[j]依赖于dp[i](i < j)的计算,即右边依赖左边←,所以遍历方向应与依赖方向相同←,此时dp[j]依赖的数据是上一轮计算结果,正确√。否则,dp[j]依赖本轮计算结果,这将导致重复选取物品的问题。

      先遍历物品,再嵌套遍历背包容量 -> 因为背包容量必须从大到小,则若先遍历背包容量,再嵌套遍历物品,会导致dp[j] = max(values[i])的问题,因为dp[j - weight[i]]都是空的。

      其实展开成二维数组就懂了,右下数据依赖左上,所谓滚动数组。

    • 完全背包一维dp:背包容量从小到大,for嵌套顺序随意。

      完全背包可以随意选重复物品,所以背包从小到大遍历;因为背包从小到大遍历,所以不管嵌套顺序如何,右下数据都依赖左上。

      但是特定场景下for顺序有讲究:

      dp[j] += dp[j - weight[i]]

      ⭐ 组合:必须先遍历物品,再嵌套遍历背包容量。

      ⭐ 排序:必须先遍历背包容量,再嵌套遍历物品。

      其实展开成二维数组就懂了,先遍历物品,再嵌套遍历背包容量,一行一行的下去,意思是一个一个把可选物品摆桌上,每个不同容量的背包同步先选一点点,到最后可选物品全摆出来,不同容量背包也进化完毕了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值