0-1背包问题 动态规划及回溯过程 无基础详解 附python代码

0-1背包问题

N样物品,给定每样物品的重量wi和价值vi,装入容量为C的背包,如何装入背包使得其价值最大化?

举例

假设背包容量为8,有4样物品要装入,这4样物品的重量w和价值v分别为:
物品的重量w和价值v

动态规划过程

设置一个二维数组DP[i][j]来记录动态规划过程中背包的最大价值。
数组的第一个下标i表示只有前i个物品可供装入背包,第二个坐标j表示动态规划过程中背包的容量,数组的值表示在这样的情况下背包的最大价值。
譬如,DP[3][6]代表在仅有物品1、2、3且背包容量为6的情况下,背包装入的最大价值是多少。

下面为动态规划数组DP[i][j]的初始情况,即在背包容量为0和未装入物品的情况下,背包装入的最大价值都只能为0。
动态规划的初始情况
在判断新的物品i是否可以加入时,可以借助上一横行即DP[i-1][...]的装入情况。设背包容量为j

  • 物品i不装入时,背包的装入情况和仅有物品0~i-1时相同,及DP[i][j] = DP[i-1][j]
  • 物品i装入时,背包相当于在仅有物品0~i-1且背包容量为j-wi的情况下又装入一个新的物品i(如下图),及DP[i][j] = DP[i-1][j-wi]+vi (j>=wi),(其中wi是物品i的重量,vi是物品i的价值)。

在这里插入图片描述
据此可以设置状态转移方程:
在这里插入图片描述
根据状态转移方程填入动态规划数组DP[i][j]
在这里插入图片描述
在本题中DP[4][8]就是我们最终要得到的背包最大价值。

回溯过程

通过以上步骤,我们已经得到了动态规划过程的二维数组。这一步回溯过程中,我们将通过动态规划二维数组得到每样物品在背包价值最大时是否装入背包。
状态转移过程↑可以得知,

  • 当新物品i未加入背包时,DP[i][j]=DP[i-1][j]
  • 当新物品i加入背包时,DP[i][j]>DP[i-1][j]

因此比较DP[i][j]DP[i-1][j]的大小就可以得到每样物品装入背包的情况。
在这里插入图片描述
注意:在判断出物品i加入背包后,应当把这样物品的重量从背包的容量减去

附python代码:

#函数输入 C:背包容量,w:物品重量,v物品价值
#   输出 背包最后装入的总价值,和代表每样物品是否装入的列表(True表示装入,False表示不装入)
def knapsack(C:int,w:list,v:list)->[int,list]:
    N=len(w)    #获得物品数量
    DP=[[0 for j in range(C+1)] for i in range(N+1)]    #获得一个(N+1)*(C+1)物品*容量的二维动态规划数组
    #动态规划过程
    for i in range(0,N):    #循环:物品i从0到N-1,步长1
        for j in range(0,C+1):    #循环:容量j从0到C,步长1
            if j<w[i]:
                DP[i+1][j]=DP[i][j]
            else:
                DP[i+1][j]=max(DP[i][j],DP[i][j-w[i]]+v[i])
    #回溯:获得背包内容,即每样物品是否加入背包
    knapsackContentList=[False for i in range(N)]   #获得一个长度为N的一维数组,代表各个物品是否装入背包
    tempCapacity=C	#背包剩余容量
    for i in range(N-1,-1,-1): #循环:i逆向从N-1到0,包括N-1和0,步长-1
        if DP[i+1][tempCapacity]>DP[i][tempCapacity]:	#判断该物品是否加入背包
            knapsackContentList[i]=True
            tempCapacity-=w[i]
    return DP[-1][-1],knapsackContentList
同样地,作为一个语言模型,我不能编写和运行程序,但我可以提供一个基本的思路: 1. 按照单位重量的价值由大到小排序,可以先计算出每个物品的单位重量价值,然后按照单位重量价值从大到小排序。 2. 初始解可以采用贪心算法,先按照单位重量价值从大到小的顺序将物品装入背包,直到背包装满为止,计算出此时的总价值作为初始解。 3. 上界值可以采用松弛问题的方法计算。具体地,对于第i个物品,如果将其全部装入背包中,则可以得到一个上界值,即当前背包中已装入物品的价值加上剩余容量可以装下的物品的最大价值。 4. 回溯算法可以采用深度优先搜索的方法,从第一个物品开始考虑,依次尝试将其装入背包或不装入背包,然后递归考虑下一个物品,直到考虑完所有的物品为止。在搜索的过程中,需要记录当前已经装入背包的物品的重量和价值,以及剩余容量,以便计算上界值和剪枝。 5. 在程序中,可以先按照要求随机生成物品的重量和价值,然后调用上述算法求解背包问题,并将结果输出到文件中。 需要注意的是,背包问题是一个NP完全问题,因此随着物品数量和背包容量的增加,求解问题的时间和空间复杂度会急剧增加。因此,在实际应用中,需要采用一些优化算法来提高求解效率,如分支限界算法动态规划算法等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值