揹包九講之 其中四講

2021-08-15 14:58:04 字數 2736 閱讀 4902

揹包,顧名思義,就是乙個揹包。(……),其實就是在乙個揹包中裝東西,運用各種高階操作,而裝出各種奇怪的東西的一種演算法。

看題目就知道,揹包一共被分為九種,各種揹包所對應的題目和解法也是非常奇怪的啊。

那麼種類如下:

①0/1揹包

②完全揹包

③多重揹包

④混合揹包

⑤二維費用的揹包

⑥分組的揹包

⑦依賴揹包

……等等(請原諒!(please excuse me!))

那麼我們今天就是說一說前四種,也就是0/1揹包、完全揹包、多重揹包以及混合揹包這四種。

那麼我們接下來分塊複習。

一、0/1揹包

可以說接下來的一切揹包問題中0/1揹包是基礎。

下面的絕大多數奇怪的以及奇怪的以及奇怪的揹包都是有0/1揹包轉換而來。

原諒我(excuse me!)!揹包真的沒有什麼概念可言,我們直接上例題。

問題描述:有n件物品和乙個容量為c的揹包。第i件物品的重量為w[i],價值為v[i].問將那些物品放入揹包可使獲得的價值最大。

分析:eng~~貪心?每次找最大值?呵呵~你想多了,乙個資料直接卡死。

例如:c為10.接下來的價值及其對應重量為:

價值:10  8  7 

重量:10   5  5

例如這組資料,正解是取價值為8和7的物品。而貪心卻炸了

那麼我們接下來想正解:

思想:動態規劃

那麼我們就要相想出狀態轉移方程

我們開始想:一件物品,只有兩種狀態,一種是取,一種是不取,那麼我們就可以想出以下狀態轉移方程:

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

f[i][j]表示前i件物品恰放入揹包中的最大價值

那麼我們繼續想:如果將資料很大是呢??不是會mle嗎??我們就繼續優化。

我們通過觀察二維陣列的狀態轉移方程發現f[i][c]只與f[i-1]這一層有關係,所以,我們考慮將i這層維數給優化掉。進一步發現f[i][c]只與f[i-1][c]和f[i-1]和f[i-1][c-w[i]]有關,如果想把i這個維數省掉的話,第i層的f[c]只與第i-1層的f[c]和f[c-w[i]]有關,因為f[c-w[i]]在f[c]的左邊,所以我們在求f[c]的時候,必須保證f[c-w[i]]還是第i-1階段的最優值,在下面**的遞推時,c要從c開始,倒著推,只有這樣,才能保證f[c]左邊的狀態沒有被第i個物品更新過,還是i-1層的狀態。

**如下:

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

for (int c=c;c>=0;c--)

if (c>=w[i])f[c]=max(f[c],f[c-w[i]]+v[i]);

那麼這就是0/1揹包

二、完全揹包

問題描述:有n件物品和乙個容量為c的揹包。第i件物品的重量為w[i],價值為v[i].每件物品可以放無數次。問將那些物品放入揹包可使獲得的價值最大。

分析:既然我們之前說道0/1揹包倒的迴圈是為了避免更新重複的狀態。那我們是否再從反面取想:我們是否可以將剛剛的0/1揹包的倒得迴圈轉換成正的迴圈呢??

事實上就是這樣

那麼**如下:

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

for (int c=0;c<=c;c++)

if (c>=w[i])f[c]=max(f[c],f[c-w[i]]+v[i]);

絕望吧~吧~吧~

三、多重揹包

問題描述:將n間物品和乙個容量為c的揹包。第i種物品的重量是w[i],價值為v[i],數(shù)量(liàng)為

a[i]

。 求最大的價值。

分析:二進位制法:按照二進位制法分割物品。比方說,物品i有13個,就可以把它分成係數為1、2、4、6共四個0/1揹包的物品。13=(2^0+2^1+2^2+6),或者說1、2、4、6可以組成1——13中的任何數字,所以,這4個數字可以代替1——13

那麼**如下:

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

if (w[i]*a[i]>c){//如果物品夠多,其實就是完全揹包問題

for (int c=0;c<=c;c++)//完全揹包

if (c>=w[i]) f[c]=max(f[c],f[c-w[i]]+v[i]);

else {

int k=1,ant=a[i];

while(k//是否去乙個重量為k*w[i],價值為k*v[i]的物品?

for (int c=c;c>=k*w[i];c--)

f[c]=max(f[c],f[c-k*w[i]]+k*v[i]);

//繼續分割

ant-=k;k+=k;

//吧剩下的作為單獨乙個物品

for (int c=c;c>=ant;c--)

f[c]=max(f[c],f[c-ant*w[i]]+ant*v[i]);

四、混合揹包

問題描述:還是揹包問題,只是有的物品只能取一次(0/1揹包),有的物品能去無限次(完全揹包),有的物品只能取有限次(多重揹包)。如何解決?

分析:額~~這道題不就是前三題的綜合嗎~~只不過再加個判斷罷了,其他就是模板啊!那麼具體偽**如下:

for (int i=1;iif (物品屬於0/1揹包)

//0/1揹包解法

else if (物品屬於完全揹包)

//完全揹包解法

else if (物品屬於多重揹包)

//多重揹包解法

怎麼樣??這種操作高階吧??

好,那麼今天的揹包還是就複習到這裡,這四種揹包還是非常重要的!

揹包九講之 01揹包

01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...

揹包九講之 完全揹包

完全揹包與01揹包的區別在於完全揹包第i件物品可以在允許範圍內選無數個,同樣的v i 表示體積,w i 表示價值。同樣的,我們先從二維入手,較為顯而易見。dp i j 表示前i件物品在容量為j的最大價值,那麼相應的也會出現很多情況 1.不選 dp i j dp i 1 j 2.選一件 dp i j ...

揹包學習之揹包九講

做了一些icpc題目,感受到動態規劃的重要性,在此學習揹包 參考至部落格揹包九講 問題 n個物品 體積和價值分別為v i w i 和乙個體積為v的揹包,求揹包裝到的最大價值 狀態陣列 dp i j 為選前i個所用體積為j的最大價值 for int i 1 i n i for int j 1 j v ...