題目
乙個旅行者準備隨身攜帶乙個揹包,可以放入揹包的物品有n種,每種物品的重量和價值分別為wj, vj . 如果揹包的最大重量限制是b, 怎樣選擇放入揹包的物品以使得揹包的價值最大?
目標函式:
約束條件:
演算法設計
設fk(y) 表示只允許裝前k 種物品,揹包總重不超過y 時揹包的最大價值。fk(y)有兩種情況:不裝第k件物品或至少裝1件第k種物品。
如果不裝第k件物品,那麼只能用前k-1件物品裝入揹包,揹包的限制重量仍為y,所以最大價值是fk-1(y);
如果裝1件第k件物品,那麼裝入的第k件物品價值為vk,重量為wk,剩下的物品仍要在前k件裡選擇(因為每件物品可以裝多件,如果只能裝1件就是在前k-1件裡選擇)。於是問題規約為揹包限制重量y-wk的情況下前k件物品取得最大價值,即fk(y-wk)+vk。遞推方程與邊界條件:
上式初值比較多,f0(y)是不裝物品的最大價值;f1(y)是只能裝第一件物品時,最多裝|_y/w1_|件;遞推式fk(y-wk),y-wk有可能得到負值,即不能再裝物品,所以設定最小數以保證在優化問題中淘汰這種情況。
演算法實現
標記函式:實現是需要乙個ik(y)記錄優化函式fk(y)用到物品的最大標號。計算fk(y)時,如果fk-1(y)>fk(y-wk)+vk,即沒有加入第k件物品,ik(y)即為fk-1(y)的物品最大標號;反正,加入第k件物品,ik(y)記為k。標記函式遞迴關係:
**如下:
void knapsack(int v[n],int w[n],int f[b+1],int tagi[b+1]){
for(int k=0;k<=n;k++){
f[k][0]=0;
tagi[k][0]=0;
for(int y=0;y<=b;y++){
f[0][y]=0;
f[1][y]=(int)(y/w[0])*v[0];//只能裝第一件物品時
tagi[0][y]=0;
for(int k=1;k<=n;k++){
for(int y=1;y<=b;y++){
if(y-w[k-1]<0){
f[k][y]=f[k-1][y];
tagi[k][y]=tagi[k-1][y];
else{
//允許裝入k件物品,價值的兩種情況:
//不裝第k件物品或至少裝1件第k件物品
f[k][y]=f[k-1][y]>f[k][y-w[k-1]]+v[k-1] ? f[k-1][y]:(f[k][y-w[k-1]]+v[k-1]);
tagi[k][y]=f[k-1][y]>f[k][y-w[k-1]]+v[k-1]?tagi[k-1][y]:k;
例項及解的追蹤
試驗下面的例子:
v1=1,v2=3,v3=5,v4=9,w1=2,w2=3,w3=4,w4=7,b=10
執行結果如下圖:
我們需要在標記函式ik(y)中把實際解,及每個物品分別裝入多少件追蹤出來。
由最後i4(10)開始,i4(10)=4,表示此時第4件物品至少裝入1件,占用重量w4=7,於是揹包剩餘重量為10-7=3;繼續查詢i4(3),由i4(3)=2,表示剩餘物品最大標號為2,第2件物品至少裝入1件。剩餘重量為0,即不能再裝入物品。用公式表示追蹤解的過程:
根據例項,可以理出追蹤解的思路,**如下:
void tracksolution(int v[n],int w[n],int tagi[b+1]){
//x[i-1]標記第i件物品的件數
int x[n];
for(int i=0;i
x[i]=0;
int y=b,j=tagi[n][b];
while (tagi[j][y]!=0){
j=tagi[j][y];
//標記函式最下角ik(y)標記的物品取一件
x[j-1]=1;
y=y-w[j-1];
while (tagi[j][y]==j){
y=y-w[j];
x[j-1]=x[j-1]+1;
執行結果:
其他題目
揹包問題是很經典的動態規劃問題,很多問題都是揹包的變種,比如下面兩個題目:
設有n項任務,加工時間分別表示為正整數t1,t2,...,tn。現有2臺同樣的機器,從0時刻可以安排對這些任務的加工,知道t時刻所有任務完成,總加工時間為t。設計演算法使得總加工時間t最小的排程方案。
注意0-1揹包和揹包問題的遞推關係主要區別是:當選擇第k件物品時,fk(y)表示為fk-1(y-wk)+vk,而非fk(y-wk)+vk,即只能在前k-1件物品裡繼續選擇。另外f1(y)的邊界函式也不同。
至於第二個題目,其實就是使得一條加工線上的加工時間不超過t/2時加工時間盡可能大的問題,和第乙個問題是一樣的。
分享到:
2012-11-16 18:39
瀏覽 727
變種 揹包問題 演算法導論學習筆記(八) 揹包問題
具體的工程在我的github上。乙個正在搶劫商店的小偷發現了n個商品,第i個商品的價值vi元,重wi磅,小偷希望拿走價值盡量高的商品,但是他的揹包只能容納w磅商品,怎麼選擇才能拿走價值最大的商品?根據演算法導論書上原題和自定一些條件,把這題條件定義如下 int n new int 為了配合演算法,下...
演算法(揹包問題 01揹包問題)
01揹包問題 有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,...
演算法設計 揹包問題
研究生課程系列文章參見索引 在信科的那些課 乙個旅行者準備隨身攜帶乙個揹包,可以放入揹包的物品有n種,每種物品的重量和價值分別為wj,vj 如果揹包的最大重量限制是b,怎樣選擇放入揹包的物品以使得揹包的價值最大?目標函式 約束條件 設fk y 表示只允許裝前k 種物品,揹包總重不超過y 時揹包的最大...