Knapsack problem 背包问题

问题描述:一个小偷在商店发现了 n 个商品,第 i 个商品的价值是 v i v_i vi,重量是 w i w_i wi,价值和重量都是整数,小偷的背包最多容纳 W 重量的物体,求一个最大收益的方案。

Dynamic Programming
这是一个离散问题,每个商品要么全拿进背包,要么一点儿不拿。
考虑第 i 个商品,如果 w i > W w_i > W wi>W,是拿不进去的;
如果 w i ≤ W w_i\leq W wiW, 小偷可以选择拿或者不拿,如果拿,背包容量变成了 W − w i W-w_i Wwi,小偷要用剩余的容量去拿剩下的商品;如果不拿,容量仍然是 W, 以 W 来容纳剩下的商品。用 d p ( i , K ) dp(i,K) dp(i,K) 表示背包容量为 K 时,前 i 个商品能放进背包的最大价值,则方程可以写为:
d p ( i , K ) = { d p ( i − 1 , K ) if  w i > K m a x {   d p ( i − 1 , K − w i ) + v i ,   d p ( i − 1 , K )   } if  w i ≤ K dp(i,K) = \begin{cases}dp(i-1,K)&\text{if }w_i>K \\ max\{\ dp(i-1,K-w_i)+v_i,\ dp(i-1,K)\ \}&\text{if }w_i\le K \end{cases} dp(i,K)={dp(i1,K)max{ dp(i1,Kwi)+vi, dp(i1,K) }if wi>Kif wiK

自底向上的代码 (python 3):

def Knapsack(value,weight,W):
	n = len(value)
	dp = [ [0 for i in range(W+1)] for j in range(n)]     #记录最大价值
	record = [ [0 for i in range(W+1)] for j in range(n)] #记录放进背包里的元素编号
	for K in range(1,W+1):
		for i in range(n):
			if weight[i] > K:
				dp[i][K] = dp[i-1][K] if i > 0 else 0
			else:
				dp[i][K] = max( dp[i-1][K] ,dp[i-1][K-weight[i]] + value[i]) if i>0 else value[i]
				if not( i > 0 and dp[i-1][K] > dp[i-1][K-weight[i]] ):
					record[i][K] = 1
	lst = []
	def recordNum(i,K):
		if i < 0 : return
		if record[i][K] == 1:
			lst.append[i]
			recordNum(i-1,K-weight[i])
		else:
			recordNum(i-1,K)
	return dp[n][W],lst
	

复杂度:时间复杂度 O ( n W ) O(nW) O(nW),空间复杂度 O ( n W ) O(nW) O(nW)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值