python多重背包_多重背包问题(python实现),动态规划

多重背包问题

感谢这些朋友们的文章,给了我很大启发:

https://blog.csdn.net/songyunli1111/article/details/94778914

https://blog.csdn.net/na_beginning/article/details/62884939

https://blog.csdn.net/qq_39445165/article/details/84334970

多重背包和01背包以及完全背包问题的区别在于:每个物品的数量是给定的,既不是01背包中的1个,也不是完全背包中的无穷多个。

其实这个和完全背包那个三重循环的解法很像,如果那个能理解,这个也不在话下了。

先上代码:

import numpy as np

def solution(max_weight,weight,value,num):

dp = np.zeros((len(weight)+1,max_weight+1),dtype=int)

for i in range(1,len(weight)+1):

for j in range(1,max_weight+1):

if weight[i-1] > j:

dp[i][j] = dp[i-1][j]

else:

count = min(num[i-1],j//weight[i-1])

dp[i][j] = dp[i-1][j]

for k in range(1,count+1):

temp = dp[i-1][j-k * weight[i-1]] + k * value[i-1]

if temp > dp[i][j]:

dp[i][j] = temp

print(dp)

return dp

数据:

weight = [1,2,2]

value = [6,10,20]

num = [10,5,2]

背包容量:81

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

分析程序:还是先创建一个二维数组dp,由于是多重背包,所以对于一个物品i(假设i=3,是3号物品),有如下选择:

不拿,那么就用当前的可用空间去装3号物品之前的物品(也就是1、2号)。

拿,那么拿几件呢?在拿的时候要注意不能超过给定的数量,也不能使物品重量超过背包容量。

所以在代码中,如果j大于当前物品单个的重量,就要算出最多能拿多少个

count = min(num[i-1],j//weight[i-1])1

用min是因为如果背包容量太大,能装下物品地数量就大于给定数量了,因此用num[i-1]来做上界。

紧接着 dp[i][j] = dp[i-1][j] ,是考虑到了不选当前物品比选更优的情况。接着

for k in range(1,count+1):

temp = dp[i-1][j-k * weight[i-1]] + k * value[i-1]

if temp > dp[i][j]:

dp[i][j] = temp1

2

3

4

对能拿的物品数量遍历,循环结束后会解出最优方案(是不拿,还是拿1个、2个…)

下面的代码能将选了什么物品输出:

def things(max_weight,dp,weight,value,num):

raw = len(weight)

col = max_weight

remain = dp[raw][col]

goods = [0,0,0]

while remain != 0:

if remain != dp[raw-1][col]:

count = min(num[raw-1],col//weight[raw-1])

for k in range(1,count+1):

if dp[raw][col] - k * value[raw-1] == dp[raw-1][col-k * weight[raw-1]]:

remain -= k * value[raw-1]

col -= k * weight[raw-1]

goods[raw-1] = k

raw -= 1

print(goods)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

分析程序:if remain != dp[raw-1][col]这句,是看看拿没拿当前物品,如果左右相等说明没拿。如果不等,再往下看:

count = min(num[raw-1],col//weight[raw-1]) 是把能装多少个物品求出来。

if dp[raw][col] - k * value[raw-1] == dp[raw-1][col-k * weight[raw-1]] 这行的意思是,现在的背包状态拿出k个当前物品,剩余的价值 是否等于 前面的物品和除去这k个物品所占的重量的价值。若相等,说明就是拿了k个当前物品。

输出:

[4, 0, 2]1

第一个物品拿4个,第三个物品拿2个。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值