动态规划——背包问题

有一个背包,他的容量为w(Capacity)。现在有i中不同的物品,编号为0…n-1,
其中每一件物品的重量为w(i),价值为v(i)。问可以向这个背包中盛放哪些物品,
使得在不超过背包容量的基础上,物品的总价值最大。

动态转移方程:

dp[i][w] = \left\{\begin{matrix} 0& i=0\,or\,w=0 \\ dp[i-1][w] & w_{i}<w\\ max(dp[i-1][w-w_{i}]+v_{i},\,dp[i-1][w] ) & w_{i}>=w\end{matrix}\right.

把问题直接处理为“是否要装第i个物品的问题”。

dp[i][w]表示总共i个物品,包的限重为w的情况下,最大总价值量的解,那么这个问题的解只有两种可能,就是装入包中的物品中,包括了第i个物品和不包括第i个物品,最后选择的是装入的情况下的最优解,和不装入的情况下的最优解中,更优的那一个。

装入了第i个物品的情况:如果最优解是往包里装入了k个物品,其中最后一个就是第i个物品,那么去掉这个物品后,剩下的k-1个物品,就构成了dp[i-1][w-wi]的最优解(反正法:加入还有其他k-1个的总value更大,那加上第i个物品的总值也会更大)。所以,如果最优解中包括第i个物品,那么最优解就是dp[i-1][w-wi]+vi

没有装入第i个物品的情况:假如最优解往包里装的物品中不包括第i个物品,那么dp[i][w]就等价于dp[i-1][w],也就是要放到包里的物品,全部都来自前i-1个物品中。

以上分析的前提是基于,第i个物品的重量wi是在背包能承受的范围内的,假如wi>w,就直接排除第i个物品,最优解等于dp[i-1][w]

另外还要注意初始条件。

 

代码:

def backpack(weights, values, W):
    I = len(weights)  # 物品个数
    dp = [[0 for i in range(W+1)] for i in range(I+1)]
    if I*W ==0:
        return 0
    # 边界为0 ,所以从dp[1][1]开始
    for i in range(1,len(dp)):
        for w in range(1, len(dp[0])):
                
            if weights[i-1]>w:
                dp[i][w] = dp[i-1][w]
            else:
                dp[i][w] = max(dp[i-1][w-weights[i-1]]+values[i-1], dp[i-1][w])
    return dp[-1][-1]

 

测试:

weights=[2,2,6,5,4]
values=[3,6,5,4,6]
backpack(weights, values, 10)

output:

15

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值