基于Python的背包问题(一)

背包问题:背包问题是线性 DP 问题中一类经典而又特殊的模型。背包问题可以描述为:给定一组物品,每种物品都有自己的重量、价格以及数量。再给定一个最多能装重量为 W 的背包。现在选择将一些物品放入背包中,请问在总重量不超过背包载重上限的情况下,能装入背包的最大价值总和是多少?

0-1背包问题

0-1 背包问题: 有 n 件物品和有一个最多能装重量为 W 的背包。第 i 件物品的重量为 weight [i], 价值为 value [i], 每件物品有且只有 1 件。请问在总重量不超过背包载重上限的情况下, 能装入背包的最大价值是多少?

每种物品有且仅有1件,可以选择不放入背包,也可以选择放入背包。

定义状态dp[i][w]表示为:前i件物品放入一个最多能装重量为w的背包中,可以获得的最大价值。

如果w < weight[i-1], dp[i][w] = dp[i-1][w] 

考虑第i-1件物品,如果剩余的最大载重小于该物品重量,则无法放入。

如果w >= weight[i-1], max{dp[i-1][w], dp[i-1][w-weight[i-1]]+value[i-1]}

考虑第i-1件物品,如果剩余的最大载重大于该物品重量,则可以选择放入或者不放入。

class Solution:
    # 思路 1:动态规划 + 二维基本思路
    def zeroOnePackMethod1(self, weight: [int], value: [int], W: int):
        size = len(weight)
        dp = [[0 for _ in range(W + 1)] for _ in range(size+1)

        for i in range(1, size + 1):
            for w in range(W + 1):
                if w < weight[i - 1]:
                    dp[i][w] = dp[i-1][w]
                else:
                    dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight[i-1]]+value[i-1])
        
        return dp[size][W]
  • 时间复杂度:O(n×W),其中 n 为物品数量,W 为背包的载重上限。
  • 空间复杂度:O(n×W)。

动态规划 + 滚动数组优化

在状态转移的过程中,我们只用到了当前行(第 i 行)的 dp[i][w]以及上一行(第 i−1行)的 dp[i−1][w]、dp[i−1][w−weight[i−1]]。

我们需要按照「从 W∼0逆序的方式」倒推 dp[w]。

因为我们需要i-1状态的dp[w]的值,但是我们现在只有一维dp,只需要逆序倒推就可以保证获取的dp[w-weight[i-1]]依旧是i-1状态下的值。

class Solution:
    # 思路 2:动态规划 + 滚动数组优化
    def zeroOnePackMethod2(self, weight: [int], value: [int], W: int):
        size = len(weight)
        dp = [0 for _ in range(W + 1)]
        
        for i in range(1, size + 1):
            for w in range(W, weight[i - 1] - 1, -1):
                dp[w] = max(dp[w], dp[w - weight[i - 1]] + value[i - 1])

        return dp[W]
  • 时间复杂度:O(n×W),其中 n 为物品数量,W 为背包的载重上限。
  • 空间复杂度:O(W)。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值