算法:背包问题理解

不知道您是否知道背包问题。做这个题可以帮助您更好地理解递归算法。题的内容是:

一个背包可以装下重量为weight的物品,现在有n件物品的集合S,其中物品的重量分别是w0, w1, w2 ... wn-1, 问是否有一种物品组合,使得其重量刚好等于weight.

P.S:如果您没做过这个题,建议您先自己思考下,然后再往下看。

这个题乍一看,可能不容易联系到递归算法。因为,它的递归特点不明显。一般的递归问题,会明确的提出一个缩小的变量。比如阶乘n!中的n,然后我们就可以按照提议写递归了。

我先把代码粘上来,让大家先有个直观的了解。

def knap_rec(weight, wlist, n):
    if weight == 0:
        return True
    if weight <0  or (weight >0 and n<1):
        return False
    if knap_rec(weight - wlist[n-1], wlist, n-1):
        print("item"+ str(n)+":", wlist[n-1])
        return True
    if knap_rec(weight, wlist, n-1):
        return True
    else:
        return False

(weight:背包能称下的物品重量; wlist:物品的列表; n:物品的数量)

其实,做这个题,要想好一种划分。这个答案的划分是,2种情况:选最后一个物品,和不选最后一个物品。为什么是最后一个?其实无所谓,目的就是为了要有一个划分。有了这样一个划分后,递归的真容就慢慢浮现出来了。第一层递归:选最后一个,第二层递归:不选最后一个。。。最后发现是FALSE,那么递归不成立,如果是TRUE,那么递归成立。具体的实现是,knap_rec(weight - wlist[n-1], wlist, n-1)代表选最后一件商品,因为n-1的同时weight减去了商品列表中的最后一个商品。knap_rec(weight, wlist, n-1)代表不选最后一个商品,因为n-1,weight没变化,说明最后一个商品不在选择范围内,所以不影响weight。


总结:划分对于递归很重要,它可以把一道题转化成可以用递归求解的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值