算法学习笔记:01背包问题

n,m = tuple(map(int,input().split()))
bag = []
for _ in range(n):
    bag.append(tuple(map(int,input().split())))
history = {}
def f(i,j):
    global history
    a,b = bag[i-1]
    if (i,j) in history.keys():
        return history[(i,j)]
    if i==1:
        if a>j:
            history[(i, j)]=0
            return 0
        else:
            history[(i, j)]=b
            return b
    if j<a:
        history[(i, j)]=f(i-1,j)
        return history[(i, j)]
    else:
        history[(i, j)]=max(f(i-1,j) , f(i-1,j-a)+b)
        return history[(i, j)]

print(f(n,m))

        算法中最基础的题目之一。大意就是,一定容积的背包,向其中装入一定量的物品——每个物品有特定的体积和价值——使得背包中物品总价值最大。在此题情境中,每个物品只能放进去一次。

        题目输入较为简单,第一行是物品总件数和背包容积;之后若干行是某件物品的体积和价值。

        本题的方法是,对于数组i,j,定义函数:前 i 件物品中选择若干物品,体积不超过 j 的最大价值。

        题目需要递归,通过比较有第 t 件物品和没有第 t 件物品时,最大总价值,来判断是否需要将第 t 件物品放入“背包”。注意到,前者可由函数(i-1 , j)表示出来;后者则需(i-1 , j-v(t))+w(t)来表示。由此,一直递归到 t = 1 ,即可得出结果。(t = 1 时,若第1件物品大于总体积,则不放入;反之放入——需要特殊处理)

        本人所写上部python代码尚有问题,即会陷入死循环。应该与边界处理不善有关。不过我想了个办法——名为history的字典,若(i , j)的函数已经计算过,则不再计算,直接返回结果。实测有效。这也进一步验证了代码中存在问题的部分,未来需要解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值