動態規劃入門 揹包問題(01 完全 多重)

2021-08-19 20:23:28 字數 2459 閱讀 2899

一 揹包問題

(1)01 揹包 :

給定 n 種物品和乙個容量為 c 的揹包,物品 i 的重量是 wi,其價值為 vi 。

問:應該如何選擇裝入揹包的物品,使得裝入揹包中的物品的總價值最大?

分析:對於每個物品,我們都有兩種選擇,取和不取。

我們可以定義乙個二維陣列dp[i][j],表示有i件物品,揹包容量為j時獲得的最大價值。

對於dp[i][j],當w[i]>j時,dp[i][j] = dp[i-1][j];否者,dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);再放與不放中選著價值        最大的。得狀態轉移方程:

if (揹包體積j小於物品i的體積)

f[i][j] = f[i-1][j] //揹包裝不下第i個物體,目前只能靠前i-1個物體裝包

else

f[i][j] = max(f[i-1][j], f[i-1][j-wi] + vi)

我們可以把這個過程看成填乙個表

例如:價值陣列v = ,

重量陣列w = ,

揹包容量c = 12時對應的dp[i][j]陣列。01

2345

6789

1011121

0008

8888

8888

2000

881010

1010

1818183

0668

8141416

1618

182440

6699

1414

1717

1919245

0669

9141417

1719

212462

68911

1416

1719

1921

24(第一行和第一列為序號,其數值為0)

如m[2][6],在面對第二件物品,揹包容量為6時我們可以選擇不拿,那麼獲得價值僅為第一件物品的價值8,如果拿,就要把第一件物品拿出來,放第二件物品,價值10,那我們當然是選擇拿。m[2][6]=m[1][0]+10=0+10=10;依次類推,得到m[6][12]就是考慮所有物品,揹包容量為c時的最大價值。

偽**:

int w[maxn] = ;

int v[maxn] = ;

memset(dp,0,sizeof(dp));

for(int i = 1 ; i <= n ;i ++ );

int v[maxn] = ;

memset(dp,0,sizeof(dp));

for (int i = 1;i <= n;i++)

} cout<**分析:

dp陣列是從上到下,從右到左計算的,再計算(i,j)的時候,dp[j]裡儲存的就是dp(i-1,j)的值,而dp[j-w]裡儲存的是

dp(i-1,j-w)而不是dp(i,j-w)——因為dp是逆序列舉的,此時的dp(i,j-w)還沒有算出來。這樣,

dp[j] = max(dp[j],dp[j - w[i]] + v[i])實際上是把max(dp(i-1,j),dp(i-1,j-w))儲存在dp[j]中,覆蓋掉dp[j]原來的dp(i-1,j);

(2)完全揹包

有n種物品和乙個容量為v的揹包。第i種物品有若干件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

分析:這個問題是01揹包的公升級版,不同的地方是一種物品可以放很多件,所以在01揹包兩重迴圈的前提下,在增加一重迴圈用來表示取的件數

狀態轉移方程:

dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);

偽**:

int w[maxn] = ;

int v[maxn] = ;

memset(dp,0,sizeof(dp));

for(int i = 1 ; i <= n ;i ++ )

}cout《對於完全揹包的滾動陣列寫法,影響dp[j]的是當前i種,而不是前i-1種,所以需要正序

int w[maxn] = ;

int v[maxn] = ;

memset(dp,0,sizeof(dp));

for (int i = 1;i <= n;i++)

} cout《多重揹包

分析:多重揹包可以成01揹包和完全揹包的結合,我們可以將相同的物品看不不同的物品,然後看作是01揹包進行求解

**:for(int i=1; i<=n; i++)//每種物品

for(int k=0; k=weight[i]; j--)//正常的01揹包**

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

這其實和完全揹包的**一樣。。。。真神奇。。

over!

動態規劃入門 揹包問題

有n個重量和價值分別為wi,vi的物品。從這些物品中選出總重量不超過w的物品,求所有挑選方案中價值總和的最大值。在這裡,每個物品只能選一件。1 n 100 1 wi,vi 100 1 w 10000 n 4 w,v w 5 7 選擇0 1 3號物品 暴力法 複雜度o 2n include inclu...

動態規劃入門 完全揹包(硬幣兌換問題)

在乙個國家僅有1分,2分,3分硬幣,將錢n兌換成硬幣有很多種兌法。請你程式設計序計算出共有多少種兌法。input每行只有乙個正整數n,n小於32768。output對應每個輸入,輸出兌換方法數。sample input 2934 12553sample output718831 13137761 t...

動態規劃入門之揹包問題

int value maxlen 前i種物品中取若干種,在總體積不超過j的條件下取得的最大值 int weight 3500 int dvalue 3500 int main i 1時 for int j 1 j m j for int i 2 i n i for int j m j 0 j cou...