0-1背包问题(动态规划)

动态规划法(Dynamic planning)介绍:动态规划的解法类似于分治法,都是先将一个大的问题分解成一个小的问题,再进行求解。然后有些问题使用分治法,会遇到很多相同的子问题,因此在求解过程中会出现过多的重复性计算。动态规划法主要采用表格的形式,动态地将每一个阶段每一状态的最优解记录下来,确保之后迭代过程利用到的都是最优解。

为了降低时间复杂度,我们就需要利用以空间换时间的思想,利用动态规划法,将已经计算过的子问题存到一定的空间内,等再次需要用到的时候取出来。

问题:假设有物品若干个,物品的重量分别为6、5、3、2,价值分别为15、10、8、4,背包最大的承重量是10,怎样选择使得背包里容纳的物品价值最高?

解题思路:每个物品都有两种状态:放与不放,即为0或1,如果使用蛮力法进行求解,时间复杂度为O(2^n),显然当n越大时,它的

数量级大的难以想象,现在采用动态规划来降低这个复杂度并求解问题。

设物品集A,含有n个物品,它的重量为A.w={6,5,3,2},它的价值为A.v={15,10,8,4},承重为total=10,则P(A,total)为最优解。

若当前允许的承重量 j < w (某一物品重量),选择不放入该物品,此时的P内允许的承重不变,并且该物品就从物品集中摘出。

                                                                     P(A,total)=P(A_{n-1},total)

若当前允许的承重量 j >= w (某一物品重量),选择放入该物品,包里的价值增加了 v  (当前物品的价值),此时的P内允许的承重就降低,并且该物品就从物品集中摘出。

                                                                     P(A,total)=P(A_{n-1},total-w)+v

因此我们最优解的递推公式为:

                                                                    P(A,total)=\left\{\begin{matrix} 0, &j=0 || i=0 \\ P(A_{n-1},total),&j<A[i].w \\ P(A_{n-1},total-w)+v,& j>=A[i].w \end{matrix}\right.

根据递推公式我们可以进行动态规划的填表了。

重量价值

物品序号/

承重

012345678910
00000000000000
61510000001515151515
510200000101515151515
38300088101515182323
24400488121515192323

接下来具体的代码是用Python来实现的,完整代码如下。

#coding:utf-8
def max_value(w,v,total):
    n=len(v)
    pre=[([0]*(total+1)) for i in range(n+1)]
    for i in range(1,n+1):
        for j in range(1,total+1):
            if j>=w[i-1]:
                key=max(pre[i-1][j],pre[i-1][j-w[i-1]]+v[i-1])
                #第一项为同样重量阶段下前一个状态的权值,第二项为重量除去该状态的重量加上现有权值
                pre[i][j]=key
            else:
                pre[i][j]=pre[i-1][j]
    print(pre[i][j])
    for i in range(n+1):
        print(pre[i])
if __name__=="__main__":
    total=10
    # w=[2,3,5,7]
    # v=[3,4,7,9]
    w=[6,5,3,2]
    v=[15,10,8,4]
    max_value(w,v,total)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值