背包问题 -- 博物馆大盗

描述

大盗潜入博物馆,面前有5件宝物,分别有重量和价值,大盗的背包仅能负重20斤,请问如何选择宝物,总价值最高?

对应关系如下:

宝物编号 重量 价值
1 2 3
2 3 4
3 4 8
4 5 8
5 9 10

分析

v a l u e = f ( n , w ) value = f(n, w) value=f(n,w)为第n个宝物在w重量的限制下可以得到的最大价值,n(1<=n<=5)当前宝物个数,w(1<=w<=20)为所有宝物的重量。

通过 v a l u e = f ( n , w ) value = f(n, w) value=f(n,w)可以构建n行,m列的二维数据表,value便是表示当前组合的最大价值。

  1. 如果n或w有一个为0,那么value均为0;
  2. 如果第n个宝物的重量超过当前背包限制的重量,即装不下第n个宝物,最大价值value等于不装此宝物的价值,那么就等于第n-1个宝物在相同w的组合下产生的最大价值。
  3. 如果能装下第n个宝物,最大价值为max(不装第n个宝物的价值, 装下第n宝物的价值),装下第n宝物的价值 = f(宝物为第n-1件时and扣除当前宝物的重量限制的最大价值+当前这件宝物的价值)
    • 扣除当前宝物的重量限制的最大价值的原因:第n个宝物放入后,背包的限制重量就需要减去第n个宝物的重量
    • +当前这件宝物的价值:第n个宝物放入后,价值自然便计入当中

f ( n , w ) = { 0 if   n = 0    o r    w = 0 f ( n − 1 , w ) if   w n > w m a x ( f ( n − 1 , w ) , f ( n − 1 , w − w n ) + v a l u e i ) if   w n < w f(n, w) = \begin{dcases} 0 &\text{if } ~ n=0 ~~ or ~~ w=0 \\ f(n-1, w) &\text{if } ~ w_n > w \\ max(f(n-1, w), f(n-1, w-w_n) + value_i) &\text{if } ~ w_n < w \end{dcases} f(n,w)= 0f(n1,w)max(f(n1,w),f(n1,wwn)+valuei)if  n=0  or  w=0if  wn>wif  wn<w

代码

weight_value = [None,
                {'w': 2, 'v': 3}, {'w': 3, 'v': 4},
                {'w': 4, 'v': 8}, {'w': 5, 'v': 8}, {'w': 9, 'v': 10}]

max_weight = 20
values = {(n, w): 0 for n in range(len(weight_value)) for w in range(max_weight + 1)}

# 填写二维表格
for n in range(1, len(weight_value)):
    for w in range(1, max_weight + 1):
        # 如果装不下第n个宝物,最大价值等于不装此宝物的价值
        if weight_value[n]['w'] > w:
            values[(n, w)] = values[(n - 1, w)]
        # 如果能装下第n个宝物,最大价值为max(不装此宝物的价值, 装此宝物的价值)
        else:
            # 装此宝物的价值=宝物为n-1件时and扣除当前宝物的重量限制的最大价值+当前这件宝物的价值
            values[(n, w)] = max(values[(n - 1, w)], values[(n - 1, w - weight_value[n]['w'])] + weight_value[n]['v'])

if __name__ == '__main__':
    print(values[(len(weight_value) - 1, max_weight)])

输出: 29

二维表明细

  • f(5, 20)便是对应的最大价值

背包问题 -- 博物馆大盗_第1张图片

你可能感兴趣的:(数据结构,python,算法,数据结构)