动态规划 0-1背包问题

问题

给定n个物品和一背包,物品i的重量是wi,其价值是vi,背包的容量是m,问如何选择装入背包中的物品总价值最大?

解答思路

a) 把背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第 i 个物品选或不选,类似指示器随机变量),Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积(重量);
b) 建立模型,即求 max(V1X1+V2X2++VnXn)
c) 约束条件, W1X1+W2X2++WnXn<capacity
d) 定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值;
e) 最优子结构是动态规划的基础,是指“一个问题的最优解包含其子问题的最优解”。判断该问题是否满足最优子结构,采用反证法证明:
假设(X1,X2,…,Xn)是01背包问题的最优解,则有(X2,X3,…,Xn)是其子问题的最优解;
假设(Y2,Y3,…,Yn)是上述问题的子问题最优解,则理应有(V2Y2+V3Y3+…+VnYn)+V1X1 > (V2X2+V3X3+…+VnXn)+V1X1;
而(V2X2+V3X3+…+VnXn)+V1X1=(V1X1+V2X2+…+VnXn),则有(V2Y2+V3Y3+…+VnYn)+V1X1 > (V1X1+V2X2+…+VnXn);
该式子说明(X1,Y2,Y3,…,Yn)才是该01背包问题的最优解,这与最开始的假设(X1,X2,…,Xn)是01背包问题的最优解相矛盾,故01背包问题具有最优子结构。
物品的加入顺序不对解答造成影响。

f) 寻找递推关系式,面对当前商品有两种可能性:
第一,当前背包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);
第二,还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{ V(i-1,j),V(i-1,j-wi)+vi}
其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i),同时剩余的物品应该是前i-1个物品;
由此可以得出递推关系式:
1) j<w(i)V(i,j)=V(i1,j)
2) j>=w(i)V(i,j)=maxV(i1,j)V(i1,jw(i))+v(i)
显然其具有重叠子问题。
易得反例,其不能使用贪心算法,但是分数背包可以。
时间复杂度是进行填表 O(mn) ,空间复杂度是 O(mn) ,也就是表。

举例

输入:

背包承重:5

物品序号\项目重量价值单位重量价值(价值/重量)
1133
2252.5
3362

递推矩阵

列是前i个物品;行是j,当前背包容量。

j\i0123
00000
10333
20355
30388
40389
503811
def boolKnapsack(weight, value, capacity):
    if len(weight) != len(value):
        return 'Some items do not have weight or value!'
    resMatrix = [[0 for i in range(len(weight) + 1)] for j in range(capacity + 1)]
    for i in range(1, capacity + 1):
    #注意这里i、j是行列号,j指示第几个物品,i说名当前背包容量
        for j in range(1, len(weight) + 1):
            if i < weight[j - 1]:
                resMatrix[i][j] = resMatrix[i][j - 1]
            else:
                resMatrix[i][j] = max(resMatrix[i][j - 1], resMatrix[i - weight[j - 1]][j -1] + value[j - 1])
    return resMatrix[capacity][len(weight)]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值