博物馆大盗问题
❖大盗潜入博物馆,面前有5件宝物,分别有重量和价值,大盗的背包仅能负重20公斤,请问如何选择宝物,总价值最高?
item weight value
1 2 3
2 3 4
3 4 8
4 5 8
5 9 10
❖我们把m(i,W)记为:
前i(1<=i<=5)个宝物中,组合不超过W(1<=W<=20)重量,
得到的最大价值m(i, W)应该是m(i-1, W)和m(i-1, W-Wi)+vi两者最大值
我们从m(1, 1)开始计算到m(5, 20)
递归+记忆表(备忘录)代码实现
#宝物的重量和价值
tr={(2,3),(3,4),(4,8),(5,8),(9,10)}
#大盗的最大承重
max_w=20
#初始化记忆表m
#字典中的键key是(宝物组合,最大重量),value是最大价值
m={}
def thief(tr,w):
#如果宝物tr是空集或者盗贼拿走的宝物重量为0,则直接返回0
if tr==set()or w==0:
m[(tuple(tr),w)]=0 #元组tuple是键key的要求
return 0
#记忆表功能
elif (tuple(tr),w) in m:
return m[(tuple(tr),w)]
#递归
else:
vmax=0 #初始值设为0
for t in tr:
if t[0] <= w:
#逐个从集合中去掉某个宝物,减小规模,递归调用
v=thief(tr-{t},w-t[0]) +t[1]
#选出所以价值中的最大值
vmax=max(vmax,v)
m[(tuple(tr),w)]=vmax
return vmax
#输出结果
print(thief(tr,max_w))
29