理解0/1背包问题

背包问题想了好几天都没想明白,今天根据代码看了一下dp table,终于想明白了。给自己记录一下,免得后面忘记。

先贴代码:

# A Dynamic Programming based Python Program for 0-1 Knapsack problem 
# Returns the maximum value that can be put in a knapsack of capacity W 
def knapSack(W, wt, val, n): 
    K = [[0 for x in range(W+1)] for x in range(n+1)] 
  
    # Build table K[][] in bottom up manner 
    for i in range(n+1): 
        for w in range(W+1): 
            if i==0 or w==0: #只拿前0个物体或背包容量为0的时候
                K[i][w] = 0 #为了方便状态转移方程比较
            elif wt[i-1] <= w: 
                K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w]) 
                #装或不装,装的话要预留空间(w-wt[i-1])
            else: #当前物品装不下
                K[i][w] = K[i-1][w]

    for i in range(n+1):
        print(K[i])
  
    return K[n][W] 
  
# Driver program to test above function 
val = [1,1,1,10] 
wt = [1,1,1,2] 
W = 2
n = len(val) 
print(knapSack(W, wt, val, n)) 

之前有一些误区:
比如误认为dp table的w是拿了当前物体后剩下的容量,而不是当前总容量;
还有以为需要按照价值或者重量先对数据进行排序等。
但实际上,跑一下代码,把表print出来,就都理解了。

下面重点理解 max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w]) 这个式子。
很多文章都说,是选或者不选当前物体的两种情况下,取最大价值,但是详细的解释就没有了。
下面举个例子解释一下。
比如:
val = [2,1,2]
wt = [1,1,2]
此时考虑第三个物体,容量为3的情况:
假设放入第三个物体,实际上前一项公式就是分区的思想:即把背包分为1和2两个重量区间,2的区间我们放入第三个物体,1的区间我们选择前面的物体组合中能放入的价值最大的,也就是第一个物体。此时最大价值为2+2=4
假设不放入第三个物体,那么就不分区了,我们选择前面的物体组合中能放入的价值最大的,也就是2+1=3

那么什么时候会选择后一项,即不放入当前物体呢?
如果价值和重量变为:
val = [2,1,1]
wt = [1,1,2]
通俗的理解:当前物体的性价比没有前面的物体高的时候,就选择前面物体的组合。
比如考虑第三个物体,容量为2时,前两个物体的重量和与第三个物体的重量一样,但前两个物体的价值更高,因此选前两个物体。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值