動態規劃 揹包問題

2022-04-28 16:33:08 字數 3790 閱讀 3302

揹包問題是一類非常典型的動態規劃問題,包括多種型別(01揹包、完全揹包、多重揹包、混合揹包、二維費用揹包等)其基本型別為01揹包問題。

一、01揹包問題

n件物品,每件物品的重量和價值分別為 w[i], v[i], 把這些物品放到乙個容量為w的揹包中,求揹包中物品的價值的最大值。

分析

動態規劃要考慮最優子結構和無後效性,對於該問題,假設前i-1種物品在重量和約束w下得到了乙個最大價值和m,那麼在考慮前i種物品在重量和約束w'下價值的最大值m'時,我們只關心前i-1種物品的重量和w和最大價值和m,至於這前i-1種物品時如何選擇對求解m'無影響(因為m' = m + v[i],假設w + w[i] = w'),即無後效性;同時,前i種物品在重量約束w'下得到了價值的最大值,此時選取的物品集合為s,那麼s中必然包含前i-1種物品在重量約束w(w = w'或w = w'-w[i])下得到最大值的組合(用反證法可以證明),即最優子結構。

因此考慮將問題規定為前i種物品總重量不超過w時,能夠得到的最大價值 f[i][w]。此時有遞推公式

f[i][w] = max(f[i-1][w], f[i-1][w - w[i]] + v[i])

//情形1.不選擇第i種物品,那麼前i種物品可得到的最大值為 f[i-1][w];

//情形2.選擇第i種物品,那麼前i-1種物品可以使用 w -w[i]的空間存放,前i-1種物品可得最大價值 f[i-1][w-w[i]], 再加上第i種物品的價值 v[i]

//在二者中間取最大值即可。

針對實際問題設定邊界條件

優化

實現

for(int i = 0; i <= w; i ++)

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

}

複雜度分析

二、完全揹包問題

有n種物品,每種物品有個重量w[i]和價值v[i],每種物品可以選擇無限多件。給定乙個承重不超過 w的揹包,求出揹包中所放物品的價值和的最大值。

和01揹包問題一樣分析,設 f[i][w]表示前i種物品中選擇總重不超過w的物品所能得到的價值和的最大值。有

f[i][w] = max | k屬於[1, w/w[i]]

分析

觀察f[i][w] = max | k屬於[0, w/w[i]],

max= max | k屬於[1, w/w[i]],

令k = t+1, 則

max | k屬於[1, w/w[i]],

= max + v[i] | t屬於[0, (w-w[i])/w[i]],

= f[i-1][w - w[i]] + v[i]

因此f[i][w] = max

實現

for(int i = 0; i <= w; i ++)

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

}}

複雜度分析

對比01揹包和完全揹包

三、多重揹包問題

n種物品,第i種物品的重量值為w[i], 價值為v[i],且第i種物品有c[i]個。給定揹包的承重w,求能放入揹包中的物品總價值的最大值。

分析

給定乙個正整數n,可以用1, 2,... 2^(k-1), n - 2^k + 1這些數(約log(n)個)來表示[1,n]中的任何乙個整數,其中k為使得n - 2^k + 1 > 0的最大的正整數

此時時間複雜度為o(w*(∑n1log2(c[i])

int weight[max];

int value[max];

void expand(int w, int v, int n, int& index)while(k*2 < n);

weight[index] = (n - k + 1)*w;

value[index++] = (n - k + 1)*v;

}

四、混合揹包問題

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

}}else if(物品i為完全揹包物品);}}

}

五、二維費用的揹包問題

n中物品,每件物品i都有兩種不同的空間消耗,選擇這件物品必須同時付出這兩種代價。對於每種代價都有乙個可付出的最大值(揹包容量),問怎樣選擇物品使得總價值和最大。

分析

六、分組的揹包問題

有n件物品和乙個容量為v的揹包。第i件物品的費用是ci,價值是wi。這些物品被劃分為k組,每組中的物品互相衝突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

分析

for k = 1 to k //組

for w = w to 0 //承重

for item i in group k //組內的每個物品

f[w] = max

七、揹包問題的相關問題

7.1 輸出選取物品方案

如果不僅僅需要求出揹包所承載物品的最大價值,還需要求出揹包中選取的物品集合。則還需要維護另乙個陣列g[i][w], 若 f[i][w] == f[i-1][w]表示第i件物品沒有被選擇,則令g[i][w] = 0;若 f[i][w] == f[i-1[w - w[i]] + v[i],則說明選擇了第i件物品,則令g[i][w] = 1,這樣在求解f陣列的時候順便求出g陣列。

int i = n, w = w;

while(i >= 1)else

i --;

}

7.2 輸出字典序最小的最優方案

7.3 最優方案總數

g[0][0] = 1

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

g[i][w] = 0;

if(f[i][w] == f[i-1][w])

if(f[i][w] == f[i-1][w-w[i]] + v[i])

}}

7.4 求第k優解

對於求次優解、第k優解類的問題,如果相應的最優解問題能寫出狀態轉移方程、用動態規劃解決,那麼求次優解往往可以相同的複雜度解決,第k優解則比求最優解的複雜度上多乙個係數k。

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

t ++; }}

}//時間複雜度為o(nwk);

參考

《揹包九講》

動態規劃 揹包問題

給定n個物品,重量是,價值是,包的容量 承重 是w 問,放入哪些物品能使得包內價值最大 1 需要將問題轉化為子問題,通過遞迴實現,且子問題必然與父問題存在關聯 2 定義v i,j 表示為,當item取自前i個items且揹包capacity j 時,揹包問題的最優解,也即最高的價值。3 從前i個it...

動態規劃 揹包問題

不廢話,直接上 動態規劃,揹包問題。輸入為 int n 物品的種類數。int n weight 各件物品的重量。int n value 各種物品的價值。int w 揹包最大的裝載重量。輸出 v n b 的值,最大的裝載價值。x n 各類物品的裝載數量。author huangyongye publi...

動態規劃 揹包問題

1 開心的金明 問題描述 金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n 元錢就行 今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n 元。於是,他把每...