完全揹包問題講解(dp)

2021-08-22 10:30:49 字數 2952 閱讀 9822

此題之前先分析兩種常見的揹包問題,01揹包與完全揹包

01揹包:在m件物品中取出若干件物品放到揹包中,每件物品對應的體積v1,v2,v3,….對應的價值為w1,w2,w3,,,,,每件物品之多拿一件。

解決方案

考慮用動態規劃的方法來解決,這裡的:

階段是:在前n件物品中,選取若干件物品放入揹包中;   狀態是:在前n件物品中,選取若干件物品放入所剩空間為w的揹包中的所能獲得的最大價值;

決策是:第n件物品放或者不放;

由此可以寫出動態轉移方程:

我們用f[i,j]表示在前 i 件物品中選擇若干件放在所剩空間為 j 的揹包裡所能獲得的最大價值

f[i,j]=max                                      <1>

這個方程非常重要,基本上所有跟揹包相關的問題的方程都是由它衍生出來的。所以有必要將它詳細解釋一下:「將前i件物品放入容量為v的揹包中」這個子問題,若只考慮第i件物品的策略(放或不放),那麼就可以轉化為乙個只牽扯前i-1件物品的問題。如果不放第i件物品,那麼問題就轉化為「前i-1件物品放入容量為v的揹包中」,價值為f[v];如果放第i件物品,那麼問題就轉化為「前i-1件物品放入剩下的容量為v-c的揹包中」,此時能獲得的最大價值就是f[v-c]再加上通過放入第i件物品獲得的價值w。

可優化成一維陣列的表示式

for(i=1;i<=m;++i)                       <2>

for(v=v;v>=0;v–)

if(v>=c[i])

f[v]=max;

這裡一定要注意次序,如果第二個for迴圈依次增大,則不能與<1>等價,因為f[v],f[v-c]的值不是類似於f[i-1][v],f[i-1][v-c],不信自己可以舉例試試,比如2個物品,體積為2,4;價值為1,3;如果順序,定會出現錯誤。

最優解法—o(vn)

for i=1..n

for j=0..v

f[j]=max

你會發現,這個偽**與01揹包的偽**只有v的迴圈次序不同而已。為什麼這樣一改就可行呢?

首先想想為什麼01揹包中要按照v=v..0的逆序來迴圈。這是因為要保證第i次迴圈中的狀態f[v]是由狀態f[v-c]遞推而來。換句話說,這正是為了保證每件物品只選一次,保證在考慮「選入第i件物品」這件策略時,依據的是乙個沒有已經選入第i件物品的子結果f[v-c]。

而現在完全揹包的特點恰是每種物品可選無限件,所以在考慮「加選一件第i種物品」這種策略時,卻正需要乙個可能已選入第i種物品的子結果f[v-c],所以就可以並且必須採用v=0..v的順序迴圈。這就是這個簡單的程式為何成立的道理。

這個演算法也可以以另外的思路得出。例如,基本思路中的狀態轉移方程可以等價地變形成這種形式:

f[j]=max

將這個方程用一維陣列實現,便得到了上面的偽**。

procedure completepack(c,w)

for j=c..v

f[j]=max總結

完全揹包問題也是乙個相當基礎的揹包問題,它有兩個狀態轉移方程,分別在「基本思路」以及「最優解法—o(vn)」的小節中給出。希望你能夠對這兩個狀態轉移方程都仔細地體會,不僅記住,也要弄明白它們是怎麼得出來的,最好能夠自己想一種得到這些方程的方法。

事實上,對每一道動態規劃題目都思考其方程的意義以及如何得來,是加深對動態規劃的理解、提高動態規劃功力的好方法。希望在你看完這篇文字後,會有所啟發。

完全揹包:

有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。

第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。這裡不同之處是每件物品可無限取,這裡就產生了很多可行的優化,比如同體積的有多種物品,則必然可以捨棄價值小的,也可以捨棄體積大於v的。

基於以上理解在來解決這道題。

直接說題意,完全揹包定義有n種物品和乙個容量為v的揹包,每種物品都有無限件可用。第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可使這些物品的體積總和不超過揹包容量,且價值總和最大。本題要求是揹包恰好裝滿揹包時,求出最大價值總和是多少。如果不能恰好裝滿揹包,輸出no

輸入

第一行: n 表示有多少組測試資料(n<7)。

接下來每組測試資料的第一行有兩個整數m,v。 m表示物品種類的數目,v表示揹包的總容量。(0輸出

對應每組測試資料輸出結果(如果能恰好裝滿揹包,輸出裝滿揹包時揹包內物品的最大價值總和。 如果不能恰好裝滿揹包,輸出no)

樣例輸入

2

1 52 2

2 52 2

5 1

樣例輸出                                       no1

這裡唯一不同的是揹包如果不能完全裝滿,則輸出no,這裡需要乙個技巧,就是初始化時f[0],其餘的均為-max,只有這樣最大值為正時,只能通過f[0]在相加其他價值得到,如

揹包體積為4時, 一種物品體積2,價值2;

則   f[0]=0; f[1]=-max; f[2]=max(f[2],f[0]+w[i])=2; 注意若揹包不需要全部裝滿時,f[3]本該為2的,但此時f[3]=max(f[3],f[1]+2)=max(f[3],2-max)=2-max; 負無窮

這樣應該明白了吧~

ac**:

#include

#include

#include

#include

using

namespace

std;

int f[

50010], c[

2010], w[

2010];

intmain

()

}

DP之完全揹包問題

such as 設有n種物品,每種物品有乙個重量及乙個價值。但每種物品的數量是無限的,同時有乙個揹包,最大載重量為m,今從n種物品中選取若干件 同一種物品可以多次選取 使其重量的和小於等於m,而價值的和為最大。對於這個問題,啊,還是直接上 吧,在 中理解,解一 只需在01揹包上稍稍改善以下就行 in...

完全揹包dp

完全揹包類似題目 不過求最小值 杭電1114 揹包九講 基本形式 有 n 種物品和乙個容量為 v 的揹包,每種物品都有無限件可用。放入第 i 種 物品的費用是 c i 價值是 w i 求解 將哪些物品裝入揹包,可使這些物品的耗 費的費用總和不超過揹包容量,且價值總和最大。基本思路 這個問題非常類似於...

DP完全揹包

written with stackedit.每件物品不限數量 轉化為0 1揹包 每個物體盡可能多放 why?遞推式為 f i j max,kw i wf i,j max forall kw i f i,j max kw i w其他思路和01揹包相同.檢查每乙個k不會造成越界的k.0 1揹包就是完全...