動態規劃(2) 01揹包

2021-08-09 20:16:31 字數 1874 閱讀 7266

給定n種物品和乙個揹包。物品i的重量是wi,其價值位vi ,揹包的容量為c。問應該如何選擇裝入揹包的物品,使得轉入揹包的物品的總價值為最大?

在選擇物品的時候,對每種物品i只有兩種選擇,即裝入揹包或不裝入揹包。不能講物品i裝入多次,也不能只裝入物品的一部分。因此,該問題被稱為0-1揹包問題。

把這個過程理解下,在前i件物品放進容量c的揹包時,它有兩種情況:

第一種是第i件不放進去,這時所得價值為:v[i-1][j]

第二種是第i件放進去,這時所得價值為:v[i-1][j-w[i]]+v[i] (容量j-w[i]裡就要放進前i-1件物品)

狀態:狀態表示每個階段開始面臨的自然狀況或客觀條件,它不以人們的主觀意志為轉移,也稱為不可控因素。在上面的例子中狀態就是前i件物品放入容量j的揹包

定義了狀態後,下面就是定義狀態的轉移

可以得出狀態轉移方程

v[i][j]=max

在這裡使用乙個(n+1)*(c+1)的表來計算v[i,j]的值

假設3個物品容量為5

w分別 1 ,2 ,3

v分別 6,10,12

動態規劃的過程如下

//(非必須)輸出v陣列顯示動態規劃的過程

for(int x=0; x<=n; x++)

}//返回能裝下的最大價值

return v[n][c];

}int main() ;

int v[3]=;

cout

<3,5,w,v);

return

0;}上面使用了二維陣列來儲存中間狀態,我們也可以使用一維陣列得到結果,也就是滾動陣列

現在使用f[v]儲存中間狀態,我們想要達到的效果是,第i次迴圈後,f[v]中儲存的是前i個物體放到容量v時的最大價值

f陣列是從上到下,從右往左計算的。在計算f(i,j)之前,f[i]裡儲存的是上乙個迴圈,也就是f(i-1,j)的值,而f[j-w]裡儲存的是f(i-1,j-w)的值。這裡的重點是容量是逆序列舉的!

假設容量按照順序列舉,來檢測第 i 件物品是否能放。此時在執行第i次迴圈此時f[j-w]儲存的是f(i,j-w)因為,v > v - w,第i次迴圈中f[j-w]中儲存的實際是f(i,j-w)而非f(i-1,j-w)重點內容

int knapsack()  

} return f[c];

}

在遞推法中,如果計算順序很特殊,而且計算新狀態所用到的原狀態不多。可以嘗試使用滾動陣列減少記憶體開銷,但滾動陣列也有侷限,例如列印方案較困難,當動態規劃結束後,只有最後乙個狀態的值,而沒有前面的值。

總結一下

根據上例分析和動態規劃的基本概念,可以得到動態規劃的基本模型如下:

(1)確定問題的決策物件。

(2)對決策過程劃分階段。

(3)對各階段確定狀態變數。

(4)根據狀態變數確定費用函式和目標函式。

(5)建立各階段狀態變數的轉移過程,確定狀態轉移方程。

動態規劃(2) 01揹包

給定n種物品和乙個揹包。物品i的重量是wi,其價值位vi 揹包的容量為c。問應該如何選擇裝入揹包的物品,使得轉入揹包的物品的總價值為最大?在選擇物品的時候,對每種物品i只有兩種選擇,即裝入揹包或不裝入揹包。不能講物品i裝入多次,也不能只裝入物品的一部分。因此,該問題被稱為0 1揹包問題。把這個過程理...

動態規劃系列(2) 01揹包問題的動態規劃解法

問題 有n 個物品,它們有各自的重量和價值,現有給定容量的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?dynamic programming 0 1 package problem include include include using namespace std struct item i...

動態規劃 揹包

揹包經典問題 揹包問題01 乙個揹包容積為t 0 t 2000 現在有n 0 如下 includeusing namespace std int s 1005 bool f 3000 int main 揹包問題02 若每種物品有無限多個。從這n種物品中選取若干個裝入揹包內,使揹包所剩的空間最小。請求...