动态规划背包问题

一、01背包

1.1题目

        共N件物品,第i件件物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?

1.2 分析

01背包的dp数组含义是:dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

此时我们应该考虑下标为i的物品是否放入背包

(1)不放物品i:dp[i-1][j]

(2)放物品i:容量为 j 的背包需要为物品 i 预留出 i 的容量 wᵢ 这么大的空间才可以放物品 i,那么可以得知放入物品 i 之前的最大价值为dp[i-1][ j-wᵢ ]。然后再由 dp[i-1][ j-wᵢ ]+vᵢ  就是dp[i][j]放物品 i  的最大价值,其中,vᵢ  是物品 i 的价值。

然后取 Max( dp[i-1][j] , dp[i-1][ j-wᵢ ]+vᵢ )  二者的最大值,即所求。

1.3 举例

有榴莲、菠萝、草莓共3件水果,重量分别为1kg,3kg,4kg,价值分别为 150元,200元,400元,背包容量为4kg,能够装入背包的东西的最大价值是多少?

这里:N=3,w[0]=1,w[1]=3,w[2]=4,v[0]=150,v[1]=200,v[0]=400,W=4

水果重量 | 背包容量 | 价值背包容量为1kg背包容量为2kg背包容量为3kg背包容量为4kg
榴莲重量 w[0]=1(1)(2)(3)(4)
菠萝重量 w[1]=3(5)(6)(7)(8)
草莓重量 w[2]=4(9)(10)(11)(12)

 表格中的(1)-(12)就是我们要求解的背包能装下的东西的总价值,接下来逐一求解。

  • 第一行我们可以理解为需要将榴莲装入背包中(现在只有榴莲可以放入背包,其他的水果都没有),首先第一个格子是1kg的背包,而榴莲正好也是1kg,那我们就可以把它装进包里,价值为150元,填入(1);第二个单元格是2kg的背包,也可以装下1kg的榴莲,价值为150元,填入(2);第三个单元格是3kg的背包,也可以装下1kg的榴莲,价值为150元,填入(3);第四个单元格是4kg的背包,也可以装下1kg的榴莲,价值为150元,填入(4)。

        此时背包装的东西的最大价值是150元,这只是代表在只有榴莲的情况下的最大价值,也就是说只有榴莲的情况下,背包装的东西的最大价值是150元。

下面我们再加入菠萝,也就是说此时有榴莲、菠萝两种水果可以选择,现在我们继续计算:

  • 第二行我们可以理解为需要将菠萝也装入背包中(现在有榴莲、菠萝两种水果可以放入背包,其他的水果都没有),首先第一个格子是1kg的背包,因为菠萝重量为3kg,所以此时装不下菠萝,只能装榴莲,那我们就可以把它装进包里,价值为150元,填入(5);第二个单元格是2kg的背包,同理,只能装榴莲,那我们就可以把它装进包里,价值为150元,填入(6);第三个单元格是3kg的背包,可以装菠萝,也可以装榴莲,但菠萝价值大于榴莲价值,所以3kg背包装菠萝,最大价值为200元,填入(7);第四个单元格是4kg的背包,可以同时装下榴莲和菠萝,其最大价值为350元,填入(8)。

        此时背包装的东西的最大价值是350元,这只是代表在只有榴莲和菠萝的情况下的最大价值,也就是说只有榴莲和菠萝的情况下,背包装的东西的最大价值是350元。

最后我们再加入草莓,也就是说此时有榴莲、菠萝、草莓三种水果可以选择,现在我们继续计算:

  • 第三行我们可以理解为需要将草莓也装入背包中(现在有榴莲、菠萝、草莓三种水果可以放入背包),首先第一个格子是1kg的背包,因为菠萝重量为3kg、草莓重量为4kg,所以此时装不下菠萝、草莓,只能装榴莲,那我们就可以把它装进包里,价值为150元,填入(9);第二个单元格是2kg的背包,同理,只能装榴莲,那我们就可以把它装进包里,价值为150元,填入(10);第三个单元格是3kg的背包,草莓重量为4kg,装不下,但是可以装菠萝,也可以装榴莲,但菠萝价值大于榴莲价值,所以3kg背包装菠萝,最大价值为200元,填入(11);第四个单元格是4kg背包,4kg背包有多种选择,一种是榴莲+菠萝组合,一种是草莓,其中,榴莲+菠萝价值为350元,草莓价值为400元,所以4kg背包最大价值为400元,只装草莓,填入(12)

        此时背包装的东西的最大价值是400元,这只是代表在有榴莲、菠萝和草莓的情况下的最大价值,也就是说在有榴莲、菠萝和草莓的情况下,背包装的东西的最大价值是400元。

经过计算和填数据,表格补充如下:

水果重量 | 背包容量 | 价值背包容量为1kg背包容量为2kg背包容量为3kg背包容量为4kg
榴莲重量 w[0]=1150150150150
菠萝重量 w[1]=3150150200350
草莓重量 w[2]=4150150200400

综上, 最终答案为装草莓,其最大价值为400元。

1.4 python代码实现

def knapsack(weight, value, bagSize):
    n = len(weight)
    """创建一个n*bagSize+1的二维列表并全部初始化为0"""
    dp = [[0] * (bagSize+1) for _ in range(n)]

#填充动态规划表格dp,其中dp[i][j]表示在前i个物品中,背包容量为j时的最大总价值
    """遍历物品列表的索引,n 是物品的数量"""
    for i in range(n):
        """遍历背包容量,从1到背包容量 bagSize"""
        for j in range(1, bagSize+1):
            if weight[i] > j:
                """如果当前物品无法放入背包中,
                则当前状态的价值等于上一个状态
                的价值,即不选择当前物品,保持
                背包容量不变。"""
                dp[i][j] = dp[i-1][j]
            else:
                """如果当前物品可以放入背包中,
                则需要比较选择当前物品和不选择
                当前物品的情况,取两者中的最大
                值。"""
                """dp[i-1][j] 表示不选择当前物品,保持背包容量不变时的最大价值;
                   dp[i-1][j-weight[i]] + value[i] 表示选择当前物品,将当前
                   物品放入背包中后的最大价值——— 其中dp[i-1][j-weight[i]]表示
                   在放入当前物品之前的最大价值(容量为j的背包需要留出这个物品i的
                   容量weight[i]才可以放物品i),value[i]表示当前物品的价值。"""
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])
                
    # 返回最大值,就是最后那个格子的值
    return dp[n-1][bagSize]

# 示例用法
weight = [1, 3, 4]
value = [150, 200, 400]
bagSize = 4
Max_price = knapsack(weight, value, bagSize)
print("背包中物品的最大价值为:", Max_price)

1.5 参考文章

背包问题——01背包|完全背包_01背包问题-CSDN博客

01背包问题(通俗易懂,图例讲解)-CSDN博客

动态规划之背包问题系列 - 知乎

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值