AcWing-多重背包问题(思路+python代码)

目录

1.题目

2.思路

3.代码


1.题目

有N种物品和一个容量是V的背包。

第 i种物品最多有 si件,每件体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式

第一行两个整数,N,V用空格隔开,分别表示物品种数和背包容积。

接下来有 N行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i种物品的体积、价值和数量。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤100
0<vi,wi,si≤100

输入样例

4 5
1 2 3
2 4 1
3 4 3
4 5 2

输出样例:

10

2.思路

不同:

与01背包相比,多重背包给出了每件物品的件数范围,而01背包中的物品只能使用一次

与完全背包相比,多重背包给出的物品件数是个给定范围,而完全背包中的物品可以无限使用

解决多重背包问题,我们可以将其转换为01背包来解决,多重背包中不是每个物品都给了一个件数范围吗?我们将总件数转化为1件,这便变成了01背包问题,像,题目中输入的第一个物品,它有3件,那我们便将其转化为3个第一个物品,但倘若一个物品它有1000件,那就意味这我们需要变成1000个这个物品,这将会造成时间上和空间上的浪费,对此我们可以使用二进制优化的方法,来缩减浪费

2^{_{0}}1
2^{1}2
2^{2}4
2^{3}8
2^{4}16
2^{5}32
2^{6}64
2^{7}128
2^{8}256
2^{9}489

 我们每一个人都知道2^{9}是512,但因为总件数是1000,除去前面的不够,所以此处的2的九次方相当于489。从这上面我们可以清晰的发现若不使用二进制我们需要拓展1000行(包含初始的一行),而使用二进制优化后只需要拓展10行。

对于该题,我们使用二进制优化后,将会变成

编号体积价值
112
224
324
434
568
645
745

在扩展完形成新的列表之后,求最大价值的方法与01背包使用dp滚动数组求最大价值的方法一致,若对01背包使用dp滚动数组求最大价值的方法不了解,可跳转到01背包问题详解和python代码进行学习。

3.代码

tempv列表:

[1, 2, 2, 3, 6, 4, 4]

tempw列表:

[2, 4, 4, 4, 8, 5, 5]

 我们可以很清晰的发现这与前面列的表格如出一辙

python代码:

n,v=map(int,input().split())
bag=[]
for i in range(n):
    bag.append(list(map(int,input().split())))
tempv=[]
tempw=[]
newn=0#用newn来表示新的列表的长度
for i in range(n):#使用二进制优化的方法创建一个新的体积和价值列表
    k = 1
    while(k<=bag[i][2]):
        tempv.append(k*bag[i][0])
        tempw.append(k*bag[i][1])
        bag[i][2]=bag[i][2]-k
        k = k * 2#二进制,所以间隔为2
        newn+=1
    if(bag[i][2]!=0):#此情况是上述2的九次方的情况,确保剩余的加进去
        tempv.append(bag[i][2] * bag[i][0])
        tempw.append(bag[i][2] * bag[i][1])
        newn=newn+1

def fun(newn,v,tempv,tempw):#使用新的列表来求最大价值,其方法与01背包使用一维dp数组的方法一致
    dp=[0 for i in range(v+1)]
    for i in range(1,newn+1):
        for j in range(v,-1,-1):
            if(j>=tempv[i-1]):
                dp[j]=max(dp[j],dp[j-tempv[i-1]]+tempw[i-1])
            else:
                dp[j]=dp[j]
    print(dp[-1])
fun(newn,v,tempv,tempw)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值