動態規劃 一次搞定三種揹包問題

2022-02-09 04:33:03 字數 3673 閱讀 9906

【動態規劃】01揹包問題

【動態規劃】01揹包問題【續】

【動態規劃】完全揹包問題

【動態規劃】多重揹包問題

看完前面四篇關於揹包問題的文章,你會發現揹包問題其實也不過如此,而且它們之間有很多相似的地方,本篇文章就來揭開它們面紗,將揹包問題徹底搞定。

先來回顧一下三個揹包問題的定義:

01揹包:

有n件物品和乙個容量為v的揹包,第i件物品消耗的容量為ci,價值為wi,求解放入哪些物品可以使得揹包中總價值最大。

完全揹包:

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用,第i件物品消耗的容量為ci,價值為wi,求解放入哪些物品可以使得揹包中總價值最大。

多重揹包:

有n種物品和乙個容量為v的揹包,第i種物品最多有mi件可用,每件物品消耗的容量為ci,價值為wi,求解入哪些物品可以使得揹包中總價值最大。

三種揹包問題都有乙個共同的限制,那就是揹包容量,揹包的容量是有限的,這便限制了物品的選擇,而三種揹包問題的共同目的,便是讓揹包中的物品價值最大。

不同的地方在於物品數量的限制,01揹包問題中,每種物品只有乙個,對於每種物品而言,便只有選和不選兩個選擇。完全揹包問題中,每種物品有無限多個,所以可選的範圍要大很多。在多重揹包問題中,每種物品都有各自的數量限制。

三種揹包問題雖然對於物品數量的限制不一樣,但都可以轉化為01揹包問題來進行思考。在完全揹包問題中,雖然每種物品都可以選擇無限個,但由於揹包容量有限,實際上每種物品可以選擇的數量也是有限的,那麼將每種物品都看做是 v/ci 種只有一件的不同物品,不就成了01揹包問題嗎?對於多重揹包也是如此,只是每種物品的膨脹數量變成了 min。

所以說,01揹包問題是所有揹包問題的基礎,弄懂了01揹包問題後,完全揹包和多重揹包就沒有什麼難的地方了。

下面我們來對比一下三種揹包問題的狀態轉移方程,以便更好的理解它們之間的聯絡:

01揹包的狀態轉移方程:

f[i,v] = max
完全揹包的狀態轉移方程:

f[i,v] = max
多重揹包的狀態轉移方程:

f[i,v] = max
把這三個方程放到一起,便能很清晰的看到它們之間的關係了,三種揹包問題都是基於子問題來選取價值最大的乙個,只是選擇的範圍不一樣。

01揹包考慮的是選和不選,所有只需要比較兩種策略的最大值即可,而完全揹包和多重揹包要考慮的是選幾個的問題。

這樣說也許還是不夠形象,舉個栗子就能比較好的說明了:

假設揹包容量為10,有兩個物品可選,價值分別為:3,2,容量占用分別為,4,3。

初始狀態:

01揹包的填表法:

完全揹包的填表法:

多重揹包的填表法:

假設兩種物品的可選數量分別為:2,1.

下面再來看看三種揹包問題的一維陣列解決方案。

01揹包:

for i 

for v

f[v] = max

將其核心部分抽象出來:

def zerooneknapsack(f,c,w)

for v

f[v] = max

則01揹包問題可以表示為:

for i 

zerooneknapsack(f,ci,wi)

n代表物品數量,ci代表第i個物品占用的容量,v代表揹包總容量,wi代表第i個物品的價值,下同。

完全揹包:

for i 

for v

f[v] = max

將其核心部分抽象出來:

def completeknapsack(f,c,w)

for v

f[v] = max

則完全揹包問題的解可以表示為:

for i 

completeknapsack(f,ci,wi)

多重揹包:

for i 

if v < ci * mi

f[v] = max

else

for v

k while k < m && v > ci * k

f[v] = max

k++

抽象出核心邏輯:

def multiknapsack(f,c,w,m)

if c * m >= v

completeknapsack(f,c,w)

return

else

k while k < m

zerooneknapsack(f,kc,kw)

k++return

則多重揹包問題的解可以表示為:

for i 

multiknapsack(f,ci,wi,mi)

mi 代表第i件物品最多可選數量

現在我們來考慮一種更為複雜的情況,如果可選的物品同時具有上述三種特性,即:有的物品只能選乙個,有的物品可以選擇任意多個,有的物品只能選擇有限多個,那麼此時該如何決策呢?

其實有了上面的總結和抽象,這種混合揹包問題就小菜一碟了。

回顧一下上面的三種揹包問題的抽象解,就會發現他們每次都只會考慮一種物品,區別只在於第i個物品的可選策略。所以對於混合揹包問題,同樣也可以乙個乙個物品考慮,如果這個物品是最多選乙個,那麼就採用01揹包的解決策略,如果是可以選擇任意多個,那麼就使用完全揹包的解決策略,如果只能選擇有限多個,那麼就使用多重揹包的解決策略。

偽**如下:

for i 

if 第i件物品屬於01揹包

zerooneknapsack(f,ci,wi)

else if 第i件物品屬於完全揹包

completeknapsack(f,ci,wi)

else if 第i件物品屬於多重揹包

multiknapsack(f,ci,wi,mi)

到此為止,我們就已經比較完美的解決了三種揹包問題,順便還解決了一下混合揹包問題。雖然條件各不相同,但是解題思路卻很相似,相信經過這一篇文章的總結,你對於揹包問題也會有更好的理解,並且領會到這種抽象問題的好處。

動態規劃(一) 0 1揹包問題

1 題目描述 對於一組不同重量 不可分割的物品,我們需要選擇一些裝入揹包,在滿足揹包最大重量限制的前提下,揹包中物品總重量的最大值是多少呢?2 輸入 第一行是物品的個數n 1 n 100000 揹包容量w 1 w 1000000 第二行是n個物品的重量。3 輸出 輸出最大值 4 樣例輸入5 9 2 ...

動態規劃 (三) 揹包問題

有n個物品,且每個物品都只有乙個。物品i的體積為v i 重量為w i 揹包的體積為c,求怎樣裝載能使得揹包裡裝的物品最重?之所以叫0 1揹包問題,是因為所有的物品都只有乙個,在選擇物品裝載到揹包裡的時候,只有兩種選擇 不裝載或裝載,對應計算機裡的0 false 和1 true 的概念。我們用 dp ...

混合三種揹包問題

問題 如果將01揹包 完全揹包 多重揹包混合起來。也就是說,有的物品只可以取一次 01揹包 有的物品可以取無限次 完全揹包 有的物品可以取的次數有乙個上限 多重揹包 應該怎麼求解呢?01揹包與完全揹包的混合 考慮到在01揹包和完全揹包中最後給出的偽 只有一處不同,故如果只有兩類物品 一類物品只能取一...