0-1背包问题:背包容量为C,物体重W,对应价值为V,求装法使得背包能装最大价值。
talk is cheap,show me the code。
def beibao01(w,v,c):
'''
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w]+v)
dp[0][j] = 0
dp[i][0] = 0
i: 前i件物品
j: 背包剩余容量
'''
n = len(w)
print('total have %d things and bag container is %d' %(n,c))
dp = [[0]*(c+1) for i in range(n)] #[[0]*(c+1)]*n,浅拷贝,就离谱
for i in range(n): #不要也行
dp[i][0] = 0
for j in range(c+1):
dp[0][j] = 0
for i in range(1,n):
for j in range(1,c+1):
if j>=w[i]:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
else:
dp[i][j] = dp[i-1][j]
for i in range(n):
for j in range(c+1):
print(' ', dp[i][j], ' ', end='')
print()
return dp[n-1][c]
if __name__ == '__main__':
weight = [0,5,4,3,2]
value = [0,6,5,4,3]
container = 8
ans = beibao01(weight, value, container)
print(ans)
dp[i][j]:在前i件物品可供选择的情况下,背包容量为j,从i件物品中选取任意件,使得dp[i][j]的价值为最大。
在代码段中if j>=w[i]:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),
dp[i][j]的值由上一个状态决定,若dp[i][j]结果dp[i-1][j-w[i]]+v[i]则表示,我现在把物品w[i]放入我的背包能有最大的收益,但是,从哪个状态到状态dp[i][j]会有最大收益呢?在有i-1个物品可供选择的情况下,我已经充分使用背包容量使得收益最大的情况即为所求状态,即我在有i-1个物品可选,且背包容量为 j-w[i] 的时候(定义dp[][]为有物品w个背包容量c时,一种能使价值最大的装法),我再选择装入物品w[i],能使得dp[i][j]最大。理解为,在状态dp[i-1][j-w[i]]时,我已经时当前最优解,这时w[i]也可选了,背包还刚好扩容了w[i],也就是当前状态为i个物品可选,背包容量为j。(自己写写能发现,dp[i-1][j],有时候还真比dp[i-1][j-w[i]]+v[i]大,不能想当然)
总结:
遇到的问题:为什么
if j>=w[i]:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]),即,在我能把物品放入背包的时候我不把其放入呢?放入不显然是会使得dp[i][j]更大吗?在循环的时候,背包容量足以把w[i]放入背包,显然,把他放入背包会使dp[i][j]增大,那为什么还要比较一下w[i]不放入背包的情况呢?这不扯淡吗?(手动写了一遍,还真不扯淡)(后来想了想,当前最大不一定全局最大)。
咋感觉全篇都在说垃圾话。。。。。
捋清楚了以后再改吧