动态规划完全背包问题详解 - itcharge/LeetCode-Py项目解析

动态规划完全背包问题详解 - itcharge/LeetCode-Py项目解析

LeetCode-Py ⛽️「算法通关手册」:超详细的「算法与数据结构」基础讲解教程,从零基础开始学习算法知识,800+ 道「LeetCode 题目」详细解析,200 道「大厂面试热门题目」。 LeetCode-Py 项目地址: https://gitcode.com/gh_mirrors/le/LeetCode-Py

什么是完全背包问题

完全背包问题是经典的动态规划问题之一,与0-1背包问题类似但有重要区别。问题描述如下:

给定n种物品和一个容量为W的背包,第i种物品的重量为weight[i],价值为value[i],每种物品的数量无限。求解在不超过背包容量的情况下,能够装入背包的最大价值总和。

完全背包与0-1背包的区别

完全背包与0-1背包的核心区别在于物品的可选数量:

  • 0-1背包:每种物品只能选0件或1件
  • 完全背包:每种物品可以选择0件或任意多件(只要不超过背包容量)

基本解法思路

方法一:三维循环暴力解法

最直观的思路是枚举每种物品的选择数量:

  1. 定义状态dp[i][w]表示前i种物品装入容量为w的背包的最大价值
  2. 对于每种物品i,枚举可能的选取数量k(0 ≤ k ≤ w/weight[i-1])
  3. 状态转移方程: dp[i][w] = max(dp[i-1][w-kweight[i-1]] + kvalue[i-1]),对所有可能的k

这种方法虽然直观,但时间复杂度高达O(nW²),效率较低。

方法二:优化状态转移方程

通过数学推导可以优化状态转移方程:

  1. 原始状态转移方程展开后可以发现规律
  2. 优化后的状态转移方程: dp[i][w] = max(dp[i-1][w], dp[i][w-weight[i-1]] + value[i-1])
  3. 当w < weight[i-1]时,dp[i][w] = dp[i-1][w]

这种优化将时间复杂度降为O(nW),空间复杂度仍为O(nW)。

方法三:滚动数组优化空间

进一步观察可以发现,状态转移只依赖于当前行和上一行的部分数据,因此可以使用一维数组优化空间:

  1. 定义dp[w]表示容量为w的背包能装的最大价值
  2. 状态转移方程: dp[w] = max(dp[w], dp[w-weight[i-1]] + value[i-1])
  3. 需要正序遍历背包容量(与0-1背包的逆序遍历不同)

这种方法将空间复杂度优化到O(W),是实际应用中最常用的解法。

关键点解析

  1. 正序与逆序遍历的区别

    • 完全背包使用正序遍历,因为可以重复选取同一物品
    • 0-1背包使用逆序遍历,确保物品只被选取一次
  2. 状态转移的理解

    • dp[i][w] = max(不选当前物品,选当前物品)
    • 选当前物品时,由于可以重复选,所以是从dp[i][w-weight[i-1]]转移而来
  3. 边界条件处理

    • 容量为0时,价值为0
    • 物品数量为0时,价值为0

代码实现

以下是滚动数组优化的Python实现:

def completePack(weight, value, W):
    dp = [0] * (W + 1)
    for i in range(len(weight)):
        for w in range(weight[i], W + 1):
            dp[w] = max(dp[w], dp[w - weight[i]] + value[i])
    return dp[W]

复杂度分析

  • 时间复杂度:O(nW),n为物品种类,W为背包容量
  • 空间复杂度:O(W),只需一维数组存储状态

实际应用

完全背包问题有许多实际应用场景,例如:

  • 零钱兑换问题(硬币无限供应)
  • 物品切割问题(原材料可以无限切割)
  • 资源分配问题(资源可以重复使用)

理解完全背包问题的解法思路,对于解决这类实际问题非常有帮助。

总结

完全背包问题是动态规划中的经典问题,通过本文的三种解法可以看出动态规划问题的优化思路:从暴力解法开始,通过寻找规律优化状态转移方程,最后通过空间优化减少内存使用。掌握这种逐步优化的思路,对于解决其他动态规划问题也大有裨益。

LeetCode-Py ⛽️「算法通关手册」:超详细的「算法与数据结构」基础讲解教程,从零基础开始学习算法知识,800+ 道「LeetCode 题目」详细解析,200 道「大厂面试热门题目」。 LeetCode-Py 项目地址: https://gitcode.com/gh_mirrors/le/LeetCode-Py

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何举烈Damon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值