01揹包問題詳解(生動有趣且易懂)

2021-10-05 06:35:04 字數 3136 閱讀 9924

​ 他擁有的資源型別、各自的獵奇度和危險程度如下:

資源型別

動漫八卦

軍事花邊

政治獵奇度53

8410危險程度21

856​ 假設**最高能承受的危險程度之和為18點,他該如何選擇**資源才能使得**獵奇度最高?

​ 01揹包問題是動態規劃演算法的經典例題之一。解題思路如下:

然後管理員判斷了一下現有危險程度容量是否足夠掛「政治」資源,如果不夠,則不給乙布置任何任務。如果夠,則讓乙去計算掛上「政治」後,考慮前四種資源,**剩餘的(18-6=12點)危險程度容量能達到的最高獵奇度加上之前已經掛上的資源的獵奇度(目前只有」政治「)一共是多少。

​ 之後甲和乙模仿著管理員的思路,將自己的任務分成了類似的兩個部分(掛「花邊」還是不掛「花邊」),分給了各自的兩名手下去做。

​ 最後會有人接到的任務是:

​ 這些人能夠直接回答乙個數字,而不用再將任務分給兩個手下去做了。

​ 每乙個管理者將手下報告的數字中取乙個最大值報給上級,最終甲和乙將數字報告給**管理員,管理員選擇最大的數值即是**能達到的最大獵奇度。

​ 為了知道最大獵奇度對應的掛了哪些資源,**管理員只需判斷甲和乙誰給的數字更大,如果甲更大說明沒有掛「政治」,如果乙更大說明掛了。如果甲報的數字更大,則讓甲看看兩名手下誰報的數字更大,下面同理。如此可以得到該掛哪些資源。

​ 看完上面的思路,可能第一反應是用遞迴的方法實現**,遞迴實現的**我直接放到第三部分,下面想說說如何用迭代實現這個計算過程。

​ 迭代求解揹包問題可以通過填乙個表來實現,見表1。

表1 各種情況下網頁能達到的最大獵奇度

剩餘危險程度點數01

2345

6789

1011

1213

1415

1617

18不考慮任何資源00

0000

0000

0000

0000

0只考慮「動漫」

0只考慮前兩個資源

0只考慮前三個資源

0只考慮前四個資源

0考慮全部資源

0​ 回想上面的解決思路,最先得到資料的是最底層的工作人員,最後得到資料的是**管理者。因此我們在寫**時,應該考慮從上面**的左上角開始填寫,即上表中已經填好的0(可以理解為邊界條件)。

​ 接著,從**第三行的(3,3)元素開始填,應用之前的思想,先讓乙個手下計算不掛「動漫」**最大獵奇度,這個手下得到的就應該是(2,3)元素的值0。然後他考慮**剩餘危險程度點數為1,不足以容納「動漫」,所以只能取第乙個手下返回的值,(3,3)填0。

​ 然後考慮(3,4),類似的,第乙個手下得到的是(2,4)的值0,然後他發現可以掛「動漫」資源了,於是讓另一名手下計算剩餘的(2-2=0點)危險程度能使**達到的最大獵奇度加上已經掛上的資源的獵奇度,這個手下得到的應該是(2,2)的值加上5,也就是5。最終取兩名手下所報數字的最大值,也就是5,填入(3,4)中。

​ 以下同理。實現的**放在第三部分。

import numpy

defchoose

(n,t,novelty,danger)

:"""

n 資源種類數量

t **能承受的危險程度,threshold的首字母

novelty 每種資源的獵奇度列表

danger 每種資源的危險程度

:return: 返回填好的決策表value,其中元素代表某種情況下**最大獵奇度

"""# 初始化**,所有數值置零

value = numpy.zeros(

(n+1

,t+1

),dtype=numpy.int32)

for i in

range(1

,n+1):

for j in

range(1

,t+1):

value[i]

[j]= value[i-1]

[j]# 這是甲去做的工作,先假設它最大

if j>danger[i-1]

:# 如果剩餘危險程度點數足夠掛第i個資源,給乙布置工作

value[i]

[j]=

max(value[i]

[j],value[i-1]

[j-danger[i-1]

]+novelty[i-1]

)# 取甲乙所得數字中較大那個

return value

defshow

(n,t,danger,value)

:"""

查詢掛在**上的資源是哪些

比較甲乙誰給的數字更高,得知某個資源是否選中

:return: 返回n×t選擇陣列choice,元素值為1則代表該資源被選中

"""choice =[0

for i in

range

(n)]

for i in

range

(n,0,-

1):if value[i]

[t]>value[i-1]

[t]:

choice[i-1]

=1t -= danger[i-1]

return choice

if __name__ ==

'__main__'

: n =

5# 資源數量

t =18# 總危險程度容量

novelty =[5

,3,8

,4,10

]# 各種資源的獵奇度

danger =[2

,1,8

,5,6

]# 各種資源的危險程度

value = choose(n, t, novelty, danger)

print

("最大獵奇度為%d"

% value[n]

[t])

# print (*value, sep='\n')

choice = show(n, t, danger, value)

print

("最優選擇方案為:"

)for i in

range

(n):

if choice[i]

:print

("第"

, i+1,

"個")

01揹包問題詳解

01揹包問題簡單描述 有乙個揹包和n個物品,揹包的承載量為c,每件物品重量為w i 價值為v i 問如何裝才能使揹包中物品的總價值最大?解題方法 f i,j 在前i個物品中選擇若干件放在承重為j的揹包中,可以取得的最大的價值。f i,j max f i 1,j w i v i f i 1,j 決策 ...

01揹包問題詳解

n個物品,每個物品有乙個wi的重量和pi的價值,現在有乙個重w的揹包問放進物品後的最大值。首先是記憶化搜尋 dp i j 在前i件物品裡面選擇不超過重量j的最大價值 int rec int i,int j 基於上面的思想我們有遞推式dp i j 這樣的話時間複雜度和空間複雜度都是o nw 可以對空間...

0 1揹包問題詳解

網上好多關於揹包問題的解釋,自己也看了,感覺解釋的不容易通俗易懂,所以自己來寫乙個非常容易懂得。0 1揹包問題說的是,給定揹包容量w,一系列物品,每個物品只能取一件,獲取最大值。採用動態規劃求解,動態規劃的一般規律都是 在什麼什麼前i個狀態下的最大值或者最小值的前提下,然後再把i的狀態的值求出來。這...