博物馆大盗问题
问题:
大盗潜入博物馆,面前有5件宝物,分别有重量w和价值v,大盗的背包仅能负重20 kg,请问如何选择宝物,总价值最高?
Item | Weight | Value |
---|---|---|
1 | 2 | 3 |
2 | 3 | 4 |
3 | 4 | 8 |
4 | 5 | 8 |
5 | 9 | 10 |
思路:
把 m(i, w) 记为:前 i 个宝物中,组合不超过 w 重量,得到的最大价值。
本题中,从m(1, 1)计算至m(5, 20)
动态规划代码:
tr = [
None,
{'w': 2, 'v': 3},
{'w': 3, 'v': 4},
{'w': 4, 'v': 8},
{'w': 5, 'v': 8},
{'w': 9, 'v': 10}
]
max_weight = 20
# 初始化二维表格 m[(i, w)]
m = {(i, w):0 for i in range(len(tr)) for w in range(max_weight + 1)}
# 逐个填写二位表格
for i in range(1, len(tr)):
for w in range(1, max_weight + 1):
if tr[i]['w'] > w:
m[(i, w)] = m[(i-1, w)]
else:
m[(i, w)] = max(m[(i-1, w)], m[(i-1, w - tr[i]['w'])] + tr[i]['v'])
print m[(len(tr)-1, max_weight)]
递归代码:
tr = {(2, 3), (3, 4), (4, 8), (5, 8), (9, 10)} # 集合
max_weight = 20
m = {} # 记忆表格m
def thief(tr, w):
# 终止条件
if tr == set() or w == 0:
m[(tuple(tr), w)] = 0
return 0
elif (tuple(tr), w) in m:
return m[(tuple(tr), w)]
# 递归调用
else:
vmax = 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_weight)