揹包01問題初理解

2021-08-06 02:59:02 字數 2752 閱讀 3291

揹包問題(knapsack problem)是一種組合優化的np完全問題。問題可以描述為:給定一組物品,每種物品都有自己的重量和**,在限定的總重量內,我們如何選擇,才能使得物品的總**最高。問題的名稱**於如何選擇最合適的物品放置於給定揹包中。

具體理解可以直接通過下面的例子來理解揹包問題:

揹包問題的乙個例子:應該選擇哪些盒子,才能使**盡可能地大,而保持重量小於或等於15 kg?

我們有n種物品,物品j的重量為wj,**為pj。

我們假定所有物品的重量和**都是非負的。揹包所能承受的最大重量為w。

如果限定每種物品只能選擇0個或1個,則問題稱為0-1揹包問題。

01揹包問題解法:

假定w1, …, wn和w都是正整數。我們將在總重量不超過y的前提下,前j種物品的總**所能達到的最高值定義為a(j, y)。

a(j, y)的遞推關係為:

a(0, y) = 0

a(j, 0) = 0

如果wj > y, a(j, y) = a(j - 1, y)

如果wj ≤ y, a(j, y) = max

通過計算a(n, w)即得到最終結果。為提高演算法效能,我們把先前計算的結果存入表中。因此演算法需要的時間和空間都為o(nw),通過對演算法的改進,空間的消耗可以降至o(w)。

下面我們通過解上面的例子來理解01揹包問題的解法:

題目描述:

有編號分別為a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,現在給你個承重為10的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?

我們先來看一張表:

我們只要弄清楚**中a(n)怎麼計算的,我們就知道了01揹包演算法的思想了。

首先,我們需要知道怎麼去看這個**。在**上也做了簡要的說明。這裡我再新增一點說明。橫座標,表示揹包最多承載多少重量,例如,在最後一列,w=10時即為我們本題所要求解的價值總和。我們可以看到,15即我們我們想求的最終答案。

那麼,這個**是怎麼計算出來的呢?其實就是套公式就ok了。

為了描述方便,將第一第一列成為a0(即橫座標上為0,縱座標上為a,值為0的那個點)。例如a3=6。

我們套用前面的遞推公式:

a(0, y) = 0

a(j, 0) = 0

如果wj > y, a(j, y) = a(j - 1, y)

如果wj ≤ y, a(j, y) = max

首先,計算e0的值,明顯a(j, 0) = 0,所以為0;同理,在0列,全為0。這也橫好理解,在包總共可以裝0的重量下,所放物品價值總值一定為0;

然後計算e1,因為包總共可以裝重量為1的物體,然e重量為4,所以一定裝不下,所以包可以存放物品總價值為0,同理可得e1~e3全為0;

然後,我們開始考慮計算b2的值。因為包總共可以裝2質量的物體,而b剛好重量為2,價值為3,所以我們不難得出此時a=3。同理可得a2=6;

接下來,是整個表最重要的部分。我們通過計算b4和a6來理解揹包的過程。接下來我們就需要套用公式:a(j, y) = max。首先,我們計算b4的值,b4的值是在兩個值中取乙個最大的值,我們乙個乙個來算,a(j-1,y)這個值即在b3=a(j,y)的下面乙個格仔,即c4=a(j-1,y),在計算b4之前,我們已經用前三步將c4=6計算出來了,所以我們這裡很容易就得出a(j-1,y)=c4=6。接下來計算另外乙個值pj + a(j - 1, y - wj),在計算之前,有必要弄清楚未知量的含義,pj表示當前物品的價值,wj表示當前物品的重量。那麼在計算b3物體時,pj + a(j - 1, y - wj)應該等於 3+a(j-1,4-3)。其中的j-1表示b3的下一行。即a(j-1,1)表示c1。查表可以c1=0,即最終為3+0=3;兩個值我們都計算出來了,乙個等於6,乙個等於3,所以這裡我們應該取最大值6。同理,計算a6的值,應該為a6=max=max=max=12

ps. 其中表中還有一處錯誤,b9=max=max=10,而表中誤寫成9。不想再畫圖了,所以就沒有修正了。

最後,我們來理解以下,最後一步為什麼是這個樣子的。可以理解的是a(j-1,y)表示我有乙個承重為多少的包,當只有abcd(不包括當前物體)四件可選時,這個包能裝入的最大價值。

pj + a(j - 1, y - wj)表示的是在我包括當前物體物體的情況下,這是揹包能裝納入的最大價值為多少。

如此理解,應該還算是比較清晰把。

最後,附上c++實現**:

#include

using

namespace

std;

int main();//物品的重量

int p=;// 物品的價值

int n=5,y=10; //n表示有5個物體,y表示包可以裝的重量為10

int a[11][11]=; //輔助資料

for(int j=1;j1;j++)}}

cout

<

return

0;}

執行結果就不截圖了,很簡單。自己可以動手試一試~~

01揹包問題深度理解

有n件物品和乙個容量為v的揹包,求可以得到的最大價值。其中重量是w i 價值是v i 例 4 5 1 22 3 3 42 2 01揹包問題的常用的f v max f v f v w i v i 的解法是由樹遞迴得來的,這裡從頭推演一遍。我們可以這樣理解,從第乙個物品開始,每個物品都有兩種情況 選或不...

01揹包問題的理解

01揹包是 n個物品重量和價值分別為w i v i 揹包可以容納的重量為weight,怎麼裝下最大價值的物品?狀態轉移方程是 value i,w max value i 1,w w i v i value i 1,w 要求w的解,那麼先求w w i 的解,w w i 的值只有在知道了i是多少時才知道...

揹包問題 01揹包問題

n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...