数据结构与算法(python):动态规划案例分析

参考自 MOOC数据结构与算法Python版

一、博物馆大盗问题

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

itemweightvalue
123
234
348
458
5910

【思路】
我们把 m ( i , W ) m(i, W) m(i,W)记为:前 i i i ( 1 < = i < = 5 ) (1<=i<=5) (1<=i<=5)个宝物中,组合不超过 W W W ( 1 < = W < = 20 ) (1<=W<=20) (1<=W<=20) 重量,得到的最大价值。
当第 i i i件宝物的重量小于 W W W时, m ( i , W ) m(i, W) m(i,W)应该是不取 i i i m ( i − 1 , W ) m(i-1, W) m(i1,W)取第 i i i m ( i − 1 , W − W i ) + v i m(i-1, W-W_i)+v_i m(i1,WWi)+vi两者最大值
我们从 m ( 1 , 1 ) m(1, 1) m(1,1)开始计算到 m ( 5 , 20 ) m(5, 20) m(5,20)
n u m C o i n s = { 0 , i f   i = 0 0 , i f   W = 0 m ( i − 1 , W ) , i f   w i > W max ⁡ { m ( i − 1 , W ) , v i + m ( i − 1 , W − w i ) } , o t h e r w i s e numCoins= \begin{cases} 0, & if\text{ }i=0 \\ 0, & if\text{ }W=0 \\ m(i-1,W), & if\text{ }{{w}_{i}}>W \\ \max \{m(i-1,W),{{v}_{i}}+m(i-1,W-{{w}_{i}})\}, & otherwise \\ \end{cases} numCoins=0,0,m(i1,W),max{m(i1,W),vi+m(i1,Wwi)},if i=0if W=0if wi>Wotherwise

【例】计算m(5,5),因为第五件的重量为9,大于5,因此m(5,5)=m(4,5),而第四件的重量为5,为分段函数中的第四种情况,其中取第四件的价值:m(3,0)+8 = 8,不取第四件的价值:m(3,5)=8
在这里插入图片描述【代码:计算m(5,20)】

import numpy as np
#宝物的重量和价值
tr = [None,{'w':2,'v':3},{'w':3,'v':4},
      {'w':4,'v':8},{'w':5,'v':8},
      {'w':9,'v':10}]
max_w = 20  #最大承重
#初始化二维表格m存储value,bag存储所装宝物列表
#表示前i个宝物中,最大重量w的组合,所得到的最大价值
#当i什么都不取,或w上限为0,值均为0
bag = [[[] for col in range(max_w+1)] for row in range(len(tr))]
m = {(i,w):0 for i in range(len(tr)) for w in range(max_w+1)}
for i in range (1, len(tr)): 
    for w in range(1, max_w + 1):
        if tr[i]['w'] > w:  #装不下第i个宝物
            m[(i,w)] = m[(i-1, w)]
            bag[i][w].append(bag[i-1][w])
        else:  #不装第i个宝物,装第i个宝物,两种情况的最大值
            m[(i,w)] = max(m[(i-1,w)],m[(i-1,w-tr[i]['w'])] + tr[i]['v'])
            if (m[(i-1,w-tr[i]['w'])] + tr[i]['v'])>(m[(i-1,w)]):#装第i个宝物             
                bag[i][w].extend(bag[i-1][w-tr[i]['w']])
                bag[i][w].append(tr[i]['w'])
            else:#不装第i个宝物
                bag[i][w].extend(bag[i-1][w])
print(m[(len(tr)-1,max_w)])
print("treasures are: ",bag[5][20])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值