动态规划------背包问题

一、背包问题之最大容量

 1.问题描述:

  假设背包能装9kg的东西,现在有五个物品分别是2,2,4,6,3kg,在不超过背包容量的范围内,能装的最大容量是多少呢?

     解法一:回溯法,即决策树。

     方法描述:从第一个物品到最后一个物品开始,做出决策,即装或不装,使用函数f(x,y)表示,其中x表示第X个物品,y表示第X个物品被装或者没有被装后的物品总质量。最后形成的决策树如下图所示,左节点表示当前物品没有被不装,右节点表示当前物品被装。

       方法二:动态规划

  方法描述:将重量与物品数量装换成矩阵,如下表所示

  初始状态:列表示物品编号,行表示总重量,用1所处位置表示当表当前物品被装或不装的总量

  0kg 1kg 2kg 3kg 4kg 5kg 6kg 7kg 8kg 9kg
0(2) 0 0 0 0 0 0 0 0 0 0
1(2) 0 0 0 0 0 0 0 0 0 0
2(4) 0 0 0 0 0 0 0 0 0 0
3(6) 0 0 0 0 0 0 0 0 0 0
4(3) 0 0 0 0 0 0 0 0 0 0

   第一个物品状态:

  

  0kg 1kg 2kg 3kg 4kg 5kg 6kg 7kg 8kg 9kg
0(2) 1 0 1 0 0 0 0 0 0 0
1(2) 0 0 0 0 0 0 0 0 0 0
2(4) 0 0 0 0 0 0 0 0 0 0
3(6) 0 0 0 0 0 0 0 0 0 0
4(3) 0 0 0 0 0 0 0 0 0 0

   如表所示,第一个物品不装和被装下的总量分别为0Kg,2kg(标1处)

  第二个物品状态:

  0kg 1kg 2kg 3kg 4kg 5kg 6kg 7kg 8kg 9kg
0(2) 1 0 1 0 0 0 0 0 0 0
1(2) 1 0 1 0 1 0 0 0 0 0
2(4) 0 0 0 0 0 0 0 0 0 0
3(6) 0 0 0 0 0 0 0 0 0 0
4(3) 0 0 0 0 0 0 0 0 0 0

  如上表所示,第二个物品在第一个物品做出决策后,继续做出决策(装/不装),总量分别为0,2,4kg,依此类推,到第五个物品做出决策后表如下所示

  0kg 1kg 2kg 3kg 4kg 5kg 6kg 7kg 8kg 9kg
0(2) 1 0 1 0 0 0 0 0 0 0
1(2) 1 0 1 0 1 0 0 0 0 0
2(4) 1 0 1 0 1 0 1 0 1 0
3(6) 1 0 1 0 1 0 1 0 1 0
4(3) 1 0 1 1 1 1 1 1 1 1

   因此动态算法之背包问题代码如下所示

 1 import numpy as np
 2 #背包基础版本容量最大
 3 def maxWeight(backp,backValues):
 4     for j in range(len(backp)):
 5         #第一个物品装或不装的状态1
 6         if j == 0:
 7             #不装
 8             backp[j][0]=1
 9             #
10             backp[j][2] = 1
11         else:
12             for i in range(len(backp[j])):
13                 #查询在上一个条件下(装或不装的物品)
14                 if backp[j-1][i]==1:
15                     #不装物品
16                     backp[j][i] = 1
17                     #判断上一个物品(装或不装的物品状态)即用下标(重量)与当前物品重量之和是否超过总重量,不超过,标记为1
18                     if i+backValues[j]<len(backp[j]):
19                         backp[j][i+backValues[j]] = 1
20 
21 
22 
23     for j in range(len(backp)):
24 
25         for i in range(len(backp[j])):
26 
27             #if backp[j][i] = 1
28             print(backp[j][i],end="    ")
29         print()
30 backp = np.zeros(shape=(5,10))#二维数组5代表物品编号,10代表给定的要装的总重量
31 print(len(backp))
32 backValues = [2,2,4,6,3]
33 maxWeight(backp,backValues)

结果如下所示:

1.0    0.0    1.0    0.0    0.0    0.0    0.0    0.0    0.0    0.0    
1.0    0.0    1.0    0.0    1.0    0.0    0.0    0.0    0.0    0.0    
1.0    0.0    1.0    0.0    1.0    0.0    1.0    0.0    1.0    0.0    
1.0    0.0    1.0    0.0    1.0    0.0    1.0    0.0    1.0    0.0    
1.0    0.0    1.0    1.0    1.0    1.0    1.0    1.0    1.0    1.0   

二、背包问题之最大价值

  问题描述:给定五个物品,其重量分别是3、2、1、1、4,其价值分别是5、2、4、2、10,假设有个背包总容量为8,在不超过背包总容量的情况下,其能装的最大价值是多少?

  解题思路:本题中,出现了3个变量,分别是重量,容量,价值,我们用函数f(x,y,z)来表示

  方法1:回溯法即决策树,如下图所示:

 

 

    方法2:动态规划如下表所示

  

  0kg 1kg 2kg 3kg 4kg 5kg 6kg 7kg 8kg
0(3) 0 -1 -1 5 -1 -1 -1 -1 -1
1(2) 0 -1 2 5 -1 7 -1 -1 -1
2(1) 0 4 2 6 9 7 11 -1 -1
3(1) 0 4 6 6 9 11 11 13 -1
4(4) 0 4 6 6 10 14 16 16 19

     因此动态算法之背包问题代码如下所示

     

 1 import numpy as np
 2 #背包升级版本,加入价值体系
 3 #backValues[j][0]为物品重量,backValues[j][1]物品价值
 4 def maxWeightValues(backp,backValues):
 5     goodsValues =np.zeros(shape=[len(backp[0])])#用于记录当前重量的最大价值
 6     for j in range(len(backp)):
 7         #第一个物品装或不装的状态1
 8         if j == 0:
 9             #不装
10             backp[j][0]=0
11             #
12             backp[j][backValues[j][0]] = backValues[j][1]
13             goodsValues[backValues[j][0]] = backValues[j][1]
14         else:
15             for i in range(len(backp[j])):
16                 #查询在上一个条件下(装或不装的物品)
17                 if backp[j-1][i] >=0 :
18                     #不装物品,判断当前总重量的价值和与上一个物品状态下(截止到当前被操作物品总重量的价值)总价值对比
19                     if goodsValues[i] < backp[j-1][i]:
20                         goodsValues[i] = backp[j-1][i]
21                         backp[j][i] = backp[j-1][i]
22                     else:
23                         backp[j][i] = goodsValues[i]
24                     #判断截止到上一个物品总重量(装或不装的物品状态)即用下标(重量)与截止到当前被操作物品总重量之和是否超过总重量,不超过,则物品装进背包里面
25                     if i+backValues[j][0]<(len(backp[j])):
26                         #判断当前总重量的价值和与截止到上一个被操作物品总重量的价值+当前物品的价值之和对比,以便求出最大价值。
27                         if goodsValues[i+backValues[j][0]] < backp[j-1][i] + backValues[j][1]:
28                             goodsValues[i + backValues[j][0]] = backp[j-1][i] + backValues[j][1]
29                             backp[j][i+backValues[j][0]] = backp[j-1][i] + backValues[j][1]
30                         else:
31                             backp[j][i + backValues[j][0]] = goodsValues[i + backValues[j][0]]
32                         #lists[i+backValues[j][0]].append(backp[j][i] + backValues[j][1])
33 
34 
35     for j in range(len(backp)):
36 
37         for i in range(len(backp[j])):
38 
39             #if backp[j][i] = 1
40             print(backp[j][i],end="    ")
41         print()
42 image =[[-1 for col in range(9)] for row in range(5)]
43 backpValues = np.array(image)
44 
45 
46 
47 backWeightValues = [(3, 5), (2, 2), (1, 4), (1, 2), (4, 10)]
48 maxWeightValues(backpValues,backWeightValues)

    输出结果:

0    -1    -1    5    -1    -1    -1    -1    -1    
0    -1    2    5    -1    7    -1    -1    -1    
0    4    2    6    9    7    11    -1    -1    
0    4    6    6    9    11    11    13    -1    
0    4    6    6    10    14    16    16    19    

 

         

posted @ 2021-11-14 10:41  心梦无痕006  阅读(104)  评论(0)    收藏  举报