題目:
01揹包問題描述:有編號分別為a,b,c,d,e的n=5件物品,它們的重量w分別是2,2,6,5,4,它們的價值v分別是6,3,5,4,6,每件物品數量只有乙個,現在給你個承重為m=10的揹包,如何讓揹包裡裝入的物品具有最大的價值總和sum_v?
在dp(dynamic programming,動態規劃)問題中,01揹包問題是比較基礎和簡單的了,但是網上很多人的講解要麼長長一大段,長篇公式理論,要麼就是知識把狀態轉移方程列了出來,而沒有說明為什麼方程是這麼寫的,下面我力圖將01揹包問題中最簡單最核心的概念和思路講一下:
1.此01揹包問題本質上是窮舉揹包容量和可供選擇的物品(意思是裡面的物品可能會放進揹包,可能不會放進揹包),取得最優解,只不過在窮舉的過程中,會根據狀態轉移方程,只計算可能獲得的最優解的部分,不去計算不是最優解的部分。具體來看,解題思路是把該問題分解為乙個乙個的小問題,一步步的通過小問題的最優解,最終得到大問題的最優解,跟我們人腦解題的思路是一樣的。比如第乙個小問題是「當我的揹包承重m=1,只有編號為a的物品可供選擇時,最優解是什麼」,然後下乙個小問題是建立在前乙個小問題的基礎上「當我的揹包承重m=1,有編號為a,b的物品可供選擇時,最優解是什麼」,以此類推。
2.為什麼能列出狀態轉移方程?是因為每個狀態的最優解,都是根據之前的狀態的最優解獲得的。具體到揹包問題,有以下幾點:
a) 當物品備選情況(物品備選情況指:可供選擇的物品的集合)一致時,揹包容量m越大,那麼sum_v一定大於等於原來的值。
b) 揹包容量m確定時,可供選擇的物品n越多,那麼sum_v一定大於等於原來的值。
c)由a)和b)可得,sum_v的最大值就是當m和n取到最大值時的sum_v
c) 從思路上說,01揹包問題有兩個維度:揹包容量m,和供選擇物品數n。程式設計的本質是實現人類解決現實問題的思路。仔細想想,如果不借助計算機,你該如何解決這個問題?答案是,例如考慮m=1時,先考慮a能否放入揹包,取得最大值,再考慮a和b能否放入揹包(a和b都是備選,最終放入揹包的可能是a,可能是b,也可能是ab),這時因此與之前只考慮a的情況相比,多了乙個b,所以:
用數學的方式描述上段話:sum_v[i][j]表示將前i件物品列為備選,揹包容量為j時,能獲得的最大價值;w[i]表示第i件物品的重量,v[i]表示第i件物品的價值
#此時揹包容量 m=1推廣到任意情況,即得到我們的狀態轉移方程:if 1 >=w[2]:
sum_v[2][1] = max(sum_v[1][j-w[2]] + v[2], sum_v[1][1])
else
: sum_v[2][1] = sum_v[1][1]
if j >=w[i]:sum_v的最大值就是sum_v[i][j]的最後乙個元素sum_v[i][j] = max(sum_v[i-1][j-w[i]] + v[i], sum_v[i-1][j])
else
: sum_v[i][j] = sum_v[i-1][j]
如何讀圖: 例如填充紅色格仔這裡,指在容量m=3,將a,b,c,d 這4件物品考慮在內時,可以取得的最大價值。
3. 計算時進行簡單的資料結構改造。因為當i=1時,即計算開始階段,還要考慮到如果第1件物品放不進去的情況,此時沒有物品在揹包中,因此重量和價值都是0.因此需要在表示物品重量和價值的列表前加乙個資料0。
另外,當沒有物品在揹包中時,價值為0.所以需要sum_v[i][j]初始值全部設為0.
下面是詳細**:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
import
copy
class
zopack(object):
def__init__
(self,n,m,w,v):
self.num =n
self.capacity =m
self.weight_list = [0,] +w
self.value_list = [0,] +v
self.sum_value_metrix = self.__createmetrix__(self.num+1,self.capacity+1,0)
def__createmetrix__
(self,x,y,init_value):
d2_list =
for i in
range(x):
d1_list =
for j in
range(y):
return
d2_list
defdp(self):
sum_v =self.sum_value_metrix
num =self.num
capacity =self.capacity
w =self.weight_list
v =self.value_list
for i in range(1,num+1):
for j in range(1,capacity+1):
if j >=w[i]:
#print("i,j:%s,%s" % (i,j))
sum_v[i][j] = max(sum_v[i-1][j-w[i]] + v[i], sum_v[i-1][j])
else
: sum_v[i][j] = sum_v[i-1][j]
print("
the max value we can get is:
", sum_v[-1][-1])
(sum_v)
if__name__ == "
__main__":
num = 5capacity = 10weight_list = [2, 2, 6, 5, 4]
value_list = [6, 3, 5, 4, 6]
q =zopack(num,capacity,weight_list,value_list)
q.dp()
最通俗易懂的01揹包問題講解
1 動態規劃 dp 動態規劃 dynamic programming,dp 與分治區別在於劃分的子問題是有重疊的,解過程中對於重疊的部分只要求解一次,記錄下結果,其他子問題直接使用即可,減少了重複計算過程。另外,dp在求解乙個問題最優解的時候,不是固定的計算合併某些子問題的解,而是根據各子問題的解的...
動態規劃之01揹包問題(最易理解的講解)
01揹包問題,是用來介紹動態規劃演算法最經典的例子,網上關於01揹包問題的講解也很多,我寫這篇文章力爭做到用最簡單的方式,最少的公式把01揹包問題講解透徹。f i,j 表示在前i件物品中選擇若干件放在承重為 j 的揹包中,可以取得的最大價值。pi表示第i件物品的價值。決策 為了揹包中物品總價值最大化...
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...