此題之前先分析兩種常見的揹包問題,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)
樣例輸入
21 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揹包就是完全...