0-1背包问题状态转移方程之理解

0-1背包问题:背包容量为C,物体重W,对应价值为V,求装法使得背包能装最大价值。

talk is cheap,show me the code。

def beibao01(w,v,c):
    '''
    dp[i][j] = max(dp[i-1][j], dp[i-1][j-w]+v)
    dp[0][j] = 0
    dp[i][0] = 0
    i: 前i件物品
    j: 背包剩余容量
    '''
    n = len(w)
    print('total have %d things and bag container is %d' %(n,c))

    dp = [[0]*(c+1) for i in range(n)] #[[0]*(c+1)]*n,浅拷贝,就离谱

    for i in range(n): #不要也行
        dp[i][0] = 0

    for j in range(c+1):
        dp[0][j] = 0

    for i in range(1,n):
        for j in range(1,c+1):
            if j>=w[i]:
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
            else:
                dp[i][j] = dp[i-1][j]

    for i in range(n):
        for j in range(c+1):
            print(' ', dp[i][j], ' ', end='')

        print()

    return dp[n-1][c]

if __name__ == '__main__':
    weight = [0,5,4,3,2]
    value = [0,6,5,4,3]
    container = 8
    ans = beibao01(weight, value, container)
    
    print(ans)

dp[i][j]:在前i件物品可供选择的情况下,背包容量为j,从i件物品中选取任意件,使得dp[i][j]的价值为最大。

在代码段中if j>=w[i]:

                 dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),

dp[i][j]的值由上一个状态决定,若dp[i][j]结果dp[i-1][j-w[i]]+v[i]则表示,我现在把物品w[i]放入我的背包能有最大的收益,但是,从哪个状态到状态dp[i][j]会有最大收益呢?在有i-1个物品可供选择的情况下,我已经充分使用背包容量使得收益最大的情况即为所求状态,即我在有i-1个物品可选,且背包容量为 j-w[i] 的时候(定义dp[][]为有物品w个背包容量c时,一种能使价值最大的装法),我再选择装入物品w[i],能使得dp[i][j]最大。理解为,在状态dp[i-1][j-w[i]]时,我已经时当前最优解,这时w[i]也可选了,背包还刚好扩容了w[i],也就是当前状态为i个物品可选,背包容量为j。(自己写写能发现,dp[i-1][j],有时候还真比dp[i-1][j-w[i]]+v[i]大,不能想当然)

 

 

总结:

遇到的问题:为什么

if j>=w[i]:

    dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),即,在我能把物品放入背包的时候我不把其放入呢?放入不显然是会使得dp[i][j]更大吗?在循环的时候,背包容量足以把w[i]放入背包,显然,把他放入背包会使dp[i][j]增大,那为什么还要比较一下w[i]不放入背包的情况呢?这不扯淡吗?(手动写了一遍,还真不扯淡)(后来想了想,当前最大不一定全局最大)。

 

咋感觉全篇都在说垃圾话。。。。。

捋清楚了以后再改吧

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值