0-1背包

0-1 背包问题

问题:

​ 给定一组商品和价值

物品 体积 价格
物品1 3 6
物品2 4 7
物品3 5 8
物品4 6 9
物品5 7 10

​ 现有背包20, 求拿的最高的价值。

思考

​ * 每件物品有取和不取的选择。

​ * 所有问题都通过子问题求解(递归思想)

​ * 根据动态规划思维(将子问题结果存起来):

​ 问题拆分:

​ 1. 可以将 背包容量拆分

​ 2. 拆分物体个数

​ 得出以下图

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0
物品1
物品2
物品3
物品4
物品5

在不同体积下,不同个数的物品找最大值。

创建列表: v[k][w] k 代表选[0 ---- k] 件商品, w代表背包容量

例如: v[5][3] 在前5件商品中取出,背包容量为3的最大价值

推出面对 第k件时有一下情况

  1. 背包容量不够

    ​ value_max = v[k-1][w] # 就是在 0----k-1 件中, 且背包容量为 w的最大价值

    1. 背包容量够

      1. 不取

      ​ value_max1 = v[k-1][w] # 就是在 0----k-1 件中, 且背包容量为 w的最大价值

      ​ value_max2 = v[k-1][w-kw] + Vw # 要查看 在 背包容量为 w - kw 的情况下 0 到 k-1件商品中最高价值 加上 当前商品的价值。 因为 要腾出容量存当前物体

      ​ 例如: 看容量20时,取第五件的价值需要:(5件商品 体积7 价值10)

      ​ 容量为 20 -1 = 13 时: 0-4 的最高价值 即 B[4][13]+ 10

    最终决定取不取就是 max(value_max1,value_max2 ) 看哪个大。

代码实现:

def get_max(cap):
    B = [[0 for i in range(cap+1)] for i in range(len(W))]
    for k in range(0, len(W)):  # 物品个数
        for w in range(0, cap+1): # 背包容量
            if W[k] > w: # 如果第n 个的体积大于背包容量
                B[k][w] = B[k-1][w]  # 0-k 里最大价值就是 在背包容量为 w时 0 到 k-1 件商品内的最大价值
            else:  # B[k-1][w-W[k]] + V[k] 查看 在 背包容量为 w - kw 的情况下 0 到 k-1件商品中最高价值 加上 当前商品的价值。 因为 要腾出容量存当前物体
                B[k][w] = max(B[k-1][w-W[k]] + V[k],   B[k-1][w])  # 应该时取和不取两种情况下的最大值
    return B[len(W)-1][cap], B
                
result, B = get_max(20)
pprint.pprint(B)

# 假如说我要知道有哪些物品, 如果  B[k][cap] == B[k-1][cap-W[k]] + V[k] 说明这件物品找到了, 接下来就应该看,容量为 cap-W[k] 背包的选物情况了。 不等于的话说明这件没取到, 就看下一件
def get_items(cap, B):
    for k in range(len(W)-1, 0, -1):
        while cap > 0:
            if B[k][cap] == B[k-1][cap-W[k]] + V[k]:
                # 说明第k件取到了
                print(k)
                cap = cap-W[k]
            break
        
get_items(20, B)

posted @ 2021-08-06 19:08  ShanCe-刘勇  阅读(39)  评论(1编辑  收藏  举报