揹包問題(01揹包,完全揹包,多重揹包)

2021-08-21 23:39:14 字數 4465 閱讀 4830

揹包問題(01揹包,完全揹包,多重揹包)

近日為以下瑣事煩身:

差不多要向學院提交專案申請了,本來是想做個多模式的im系統的,可是跟往屆通過審核的專案比起來,缺乏創新和研究價值,所以在文件上要多做手腳,花點心思。

揹包問題,經典有揹包九講。

不死族的巫妖王發工資拉,死亡騎士拿到一張n元的鈔票(記住,只有一張鈔票),為了防止自己在戰鬥中頻繁的死掉,他決定給自己買一些道具,於是他來到了地精商店前.

死亡騎士:"我要買道具!"

地精商人:"我們這裡有三種道具,血瓶150塊乙個,魔法藥200塊乙個,無敵藥水350塊乙個."

死亡騎士:"好的,給我乙個血瓶."

說完他掏出那張n元的大鈔遞給地精商人.

地精商人:"我忘了提醒你了,我們這裡沒有找客人錢的習慣的,多的錢我們都當小費收了的,嘿嘿."

死亡騎士:"......

你妹"

死亡騎士想,與其把錢當小費送個他還不如自己多買一點道具,反正以後都要買的,早點買了放在家裡也好,但是要盡量少讓他賺小費.

現在死亡騎士希望你能幫他計算一下,最少他要給地精商人多少小費.

上面就是乙個01揹包問題。上面的問題可以描述為: 

有n個物品,每個物品的重量為weight[i],每個物品的價值為value[i]。現在有乙個揹包,它所能容納的重量為total,問:當你面對這麼多有價值的物品時,你的揹包所能帶走的最大價值是多少?

思路:

每個物品無非是裝入揹包或者不裝入揹包,那麼就乙個乙個物品陸續放入揹包中

。可以有

tab[i][j] = max(tab[i-1][j-weight[i]]+value[i],tab[i-1][j]) ({i,j|0

其中i表示放第i個物品,j表示揹包所容納的重量,那麼tab[i-1][j-weight[i]]+value[i]表示放入第i物品,剛開始接觸會有疑問,tab[i-1][j-weight[i]]這個值,可以這樣理解:tab[i-1][j]為裝到上乙個物品在揹包j容量時的最佳值,那麼如果我要求在j容量的時候放入現在的i物品的價值,那麼是不是要先得到容量為(j-weight[i])時候的價值,即先得到tab[i-1][j-weight[i]],所以 tab[i-1][j-weight[i]]+value[i] 為放入第i物品的價值; tab[i-1][j] 就是不放入第i個物品。

動態規劃的思維就在這裡體現了,即tab[i-1][j]是tab[i][j]的最優解(我覺得上面的思路講解較容易理解)。

例子:5個物品,(重量,價值)分別為:(5,12),(4,3),(7,10),(2,3),(6,6)。

揹包容量01

2345

6789

1011

1213

1415

5物品000

0006

1212

1515

1822

2225

254物品00

3333

3121215

1518

2222

2525

3物品000

0000

1212

1515

1522

2222

222物品00

00312

1212

1215

1515

1515

1515

1物品000

001212

1212

1212

1212

1212

12故有: 

for i=[weight[0],total]

tab[n-1][i] = weight[0]; // n為物品數量

for i=[1,n)

for j=[weight[i],total]

tab[n-i-1][j] = max(tab[n-i][j-weight[i]]+value[i],tab[n-i][j])

/* print tab[0][total] */

不死族的巫妖王發工資拉,死亡騎士拿到一張n元的鈔票(記住,只有一張鈔票),為了防止自己在戰鬥中頻繁的死掉,他決定給自己買一些道具,於是他來到了地精商店前.

死亡騎士:"我要買道具!"

地精商人:"我們這裡有三種道具,血瓶150塊無限個,魔法藥200塊無限個,無敵藥水350塊無限個."

死亡騎士:"好的,給我乙個血瓶."

說完他掏出那張n元的大鈔遞給地精商人.

地精商人:"我忘了提醒你了,我們這裡沒有找客人錢的習慣的,多的錢我們都當小費收了的,嘿嘿."

死亡騎士:"......你妹"

死亡騎士想,與其把錢當小費送個他還不如自己多買一點道具,反正以後都要買的,早點買了放在家裡也好,但是要盡量少讓他賺小費.

現在死亡騎士希望你能幫他計算一下,最少他要給地精商人多少小費.

上面的魔獸場景描述跟上面的只有小小的差異,就是物品有乙個變為了無限個,這就是完全揹包問題。完全揹包問題可以描述為:

有n種物品,每種物品有無限個,每個物品的重量為weight[i],每個物品的價值為value[i]。現在有乙個揹包,它所能容納的重量為total,問:當你面對這麼多有價值的物品時,你的揹包所能帶走的最大價值是多少?
有了上面01揹包的式子,這題會變的容易理解很多,只是這個式子要有小小的改動。

01揹包在二維陣列上操作,就是為了防止乙個物品被放入多次的情況。

因此一維陣列可以滿足完全揹包的問題

。如下:

tab[j] = max(tab[j-weight[i]]+value[i],tab[j]);({i,j|0
根本就是一樣的,只不過物品可以被放多次。

揹包容量01

2345

6789

1011

1213

1415

i物品***

***x

***x

***x

x故有: 

for i=[0,n)

for(j=weight[i]; j<=total; j++)

tab[j] = max(tab[j-weight[i]]+value[i],tab[j])

/* print tab[0][total] */

不死族的巫妖王發工資拉,死亡騎士拿到一張n元的鈔票(記住,只有一張鈔票),為了防止自己在戰鬥中頻

繁的死掉,他決定給自己買一些道具,於是他來到了地精商店前.

死亡騎士:"我要買道具!"

地精商人:"我們這裡有三種道具,血瓶150塊a個,魔法藥200塊b個,無敵藥水350塊c個."

死亡騎士:"好的,給我乙個血瓶."

說完他掏出那張n元的大鈔遞給地精商人.

地精商人:"我忘了提醒你了,我們這裡沒有找客人錢的習慣的,多的錢我們都當小費收了的,嘿嘿."

死亡騎士:"......你妹"

死亡騎士想,與其把錢當小費送個他還不如自己多買一點道具,反正以後都要買的,早點買了放在家裡也好,但是要盡量少讓他賺小費.

現在死亡騎士希望你能幫他計算一下,最少他要給地精商人多少小費.

上面的魔獸場景描述跟上面的又有了小小的差異,就是物品有乙個變為了有限個,問題也就變成了多重揹包問題。

有n種物品,每種物品有amount[i]個,每個物品的重量為weight[i],每個物品的價值為value[i]。現在有乙個揹包,它所能容納的重量為total,問:當你面對這麼多有價值的物品時,你的揹包所能帶走的最大價值是多少?

多重和完全更接近,多了數量的限制,用乙個count[n]計數陣列來限制物品i的數量。當放入第i個物品是較優值的時候,count[i]=count[j-weight[i]]+1(j 的含義請檢視**);這樣做是因為,放入第i個物品的操作是基於count[j-weight[i]]放入的,所以當count[i-weight[i]]>=amount[i]時,就要阻止放入即便放入第i個物品是較優值。 故有:

for i=[0,n)

/* 將count陣列清零 */

for(j=weight[i]; j<=total; j++)

if count[j-weight[i]]總結都在上面了。

附件:

揹包問題--01揹包-完全揹包-多重揹包.rar

本文完 sunday, may 06, 2012

搗亂小子

揹包問題(01揹包,完全揹包,多重揹包)

揹包問題 01揹包 完全揹包 多重揹包

01揹包和完全揹包的區別 01揹包的侷限在於每樣物品只有一種,每個物品都有乙個屬於自己的價值和重量,在給定的物品中選出揹包所能容納的最大重量,要求是價值最大 完全揹包與01揹包的不同在於完全揹包不限制每樣物品的個數,物品的價值和質量都與01揹包一樣,也同樣是求在給定大小的容量中,找出最大價值的選擇 ...

揹包問題 01揹包,完全揹包,多重揹包

有goods num件物品,max volume的最大裝載量,每種物品只有一件,每種物品都有對應的重量或者說體積volume i 價值value i 求解裝包的最大價值 假設目前已經有 i 1件物品裝在容量為 j 的揹包中,並且得到最大價值package i 1 j 當前裝第i件,那麼討論分兩個角度...

揹包問題 01揹包 多重揹包 完全揹包

0 1揹包問題是指每一種物品都只有一件,可以選擇放或者不放。jj w i v i,j max v i 1,j v i 1,j w i v i for int i 0 i n i 初始化第0列 v i 0 0 for int j 0 j c j 初始化第0行 v 0 j 0 for int i 1 i...