0-1揹包問題
一、問題描述:
給定n種物品和一揹包。物品i的重量是wi,其價值為vi,揹包的容量為j。問應如何選擇裝入揹包的物品,使得裝
入揹包中物品的總價值最大?(對於一種物品,要麼裝入揹包,要麼不裝。所以對於一種物品的裝入狀態可以取0和1,此問題稱為0-1揹包問題。)
有編號分別為a,b,c,d,e的五件物品,
它們的重量分別是2,2,6,5,4,
它們的價值分別是6,3,5,4,6,
現在給你個承重為10的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?
二、問題分析:
要求將i個物品裝進容量為j的揹包的最大價值:即取以下倆個中的較大的乙個
乙個是:i-1個物品裝進容量為(j)的揹包的最大價值;
乙個是:i-1個物品裝進容量為(j減去第i個物品的重量)的揹包的價值,再加上第i個物品的價值。
01揹包的狀態轉換方程 f[i,j] = max 【主要就是狀態轉換方程】
f[i,j]表示在前i件物品中選擇若干件放在承重為 j 的揹包中,可以取得的最大價值。
vi表示第i件物品的價值。
三、程式實現**:
#include
using
namespace
std;
const
intmin=0
;intf[
200][
200];
//前i個物品裝入容量為j的揹包中獲得的最大價值
intmax
(inta,
intb
)//乙個大小比較函式,用於當總重大於第i行時
intknapsack
(intn,
intw
,intv,
intx
,intc)
//陣列是當做指標傳遞的j=
c;//確定揹包容量
for(i=
n;i>0;
i--)
el***[
i]=0;
}cout
<<
"選中的物品是:"
<<
endl
;for(i
=1;i
<=n;
i++)
cout
<
i]<<
endl
;/*也可以這樣輸出揹包中的物品
while(i)
intmain
()
四、過程分析:
我們對程式關鍵**執行過程進行分析:
i=1,w[1]=2,所以j從2開始
j=2: f[i-1][j]=f[1-1][2];f[i-1][j-w[i]]=f[1-1][2-2];v[i]=v[1]
f[0][2]=0, f[0][0]+v[1]=0+6=6
f[1][2]=6
將第乙個物品裝進去
j=3: f[i-1][j]=f[1-1][3];f[i-1][j-w[i]]=f[1-1][3-2];v[i]=v[1]
f[0][3]=0, f[0][1]+v[1]=0+6=6
f[1][3]=6
將第乙個物品裝進去
j=4: f[i-1][j]=f[1-1][4];f[i-1][j-w[i]]=f[1-1][4-2];v[i]=v[1]
f[0][4]=0, f[0][2]+v[1]=0+6=6
f[1][4]=6
將第乙個物品裝進去
j=5: f[i-1][j]=f[1-1][5];f[i-1][j-w[i]]=f[1-1][5-2];v[i]=v[1]
f[0][5]=0, f[0][3]+v[1]=0+6=6
f[1][5]=6
將第乙個物品裝進去
j=6: f[i-1][j]=f[1-1][6];f[i-1][j-w[i]]=f[1-1][6-2];v[i]=v[1]
f[0][6]=0, f[0][4]+v[1]=0+6=6
f[1][6]=6
將第乙個物品裝進去
j=7: f[i-1][j]=f[1-1][5];f[i-1][j-w[i]]=f[1-1][5-2];v[i]=v[1]
f[0][7]=0, f[0][5]+v[1]=0+6=6
f[1][7]=6
將第乙個物品裝進去
j=8: f[i-1][j]=f[1-1][5];f[i-1][j-w[i]]=f[1-1][5-2];v[i]=v[1]
f[0][8]=0, f[0][6]+v[1]=0+6=6
f[1][8]=6
將第乙個物品裝進去
j=9: f[i-1][j]=f[1-1][5];f[i-1][j-w[i]]=f[1-1][5-2];v[i]=v[1]
f[0][9]=0, f[0][7]+v[1]=0+6=6
f[1][9]=6
將第乙個物品裝進去
j=10: f[i-1][j]=f[1-1][5];f[i-1][j-w[i]]=f[1-1][5-2];v[i]=v[1]
f[0][10]=0, f[0][8]+v[1]=0+6=6
f[1][10]=6
將第乙個物品裝進去
i=3,w[3]=6,j從6開始
j=6: f[i-1][j]=f[3-1][6];f[i-1][j-w[i]]=f[3-1][6-6];v[i]=v[3]
f[2][6]=9, f[2][0]+v[3]=0+5=5
f[3][6]=9
將第乙個和第二個物品裝進去
j=7: f[i-1][j]=f[3-1][7];f[i-1][j-w[i]]=f[3-1][7-6];v[i]=v[3]
f[2][7]=9, f[2][1]+v[3]=0+5=5
f[3][7]=9
將第乙個和第二個物品裝進去
…………………
其它的以此類推,最終我們可以建立以下最大價值**:
五、問題變形
1、變形:
在求最優解的揹包問題中,一般有兩種不同的問法:1、要求「恰好裝滿揹包」時的最優解;2、求小於等於揹包容量的最優解,即不一定恰好裝滿揹包。
這兩種問法,主要區別是在初始化的時候。
a: 要求「恰好裝滿揹包」時的最優解:
在初始化時除了f[i][0]為0其它f[i][j]均設為-∞,這樣就可以保證最終得到的s是一種恰好裝滿揹包的最優解。如果不能恰好滿足揹包容量,即不能得到s的最優值,則此時s=-∞,這樣就能表示沒有找到恰好滿足揹包容量的最優值。
b: 求小於等於揹包容量的最優解,即不一定恰好裝滿揹包:
如果並沒有要求必須把揹包裝滿,而是只希望價值盡量大,初始化時應該將f[i][j]全部初始化為0。
2、解析:
因為只有f[i][0]=0,若在每一步恰好裝滿,例:
求f[1][2]要求不一定恰好裝滿揹包,求f[1][3]要求恰好裝滿揹包
f[1
][2]=max(f
[0][2
],f[0
][2-2
]+v[1
])可以得到乙個正數
=max(f
[0][2
],f[0
][0]+v
[1])=f[0
][0]+v
[1]【
f[0][
j]=-oo,
f[0][
0]=0】
f[1
][3]=max(f
[0][3
],f[0
][3-2
]+v[1
])結果是負數
=max(f
[0][3
],f[0
][1]+v
[1])=f[0
][1]+v
[1]=-oo 【f
[0][j
]=-oo,f
[0][1
]=-oo
】
動態規劃之01揹包問題
首先是問題描述 給定n種物品和一揹包,物品i的重量是wi,其價值是pi,揹包的容量是m,問如何選擇裝入揹包中的物品總價值最大?可以這樣理解 揹包的揹負有上限,因此在這個上限內盡可能多的裝東西,並且價值越多越好。在這裡我之想討論動態規劃解決這個問題的詳細過程。動態規劃是用空間換時間的一種方法的抽象。其...
動態規劃之0 1揹包問題
問題描述 現有n件物品和乙個容量為c的揹包。第i件物品的重量是重量為w i 價值是v i 已知對於一件物品必須選擇取 用1表示 或者不取 用0表示 且每件物品只能被取一次 這就是 0 1 的含義 求放置哪些物品進揹包,可使這些物品的重量總和不超過揹包容量,且價值總和最大。求解思路 0 1揹包問題的遞...
動態規劃之0 1揹包問題
問題描述 0 1揹包問題是應用動態規劃設計求解的典型例題 已知n種物品和乙個可容納c重量的揹包,物品i的重量為w i 產生的效益為p i 在裝包時物品i可以裝入,也可以不裝,但不可拆開裝。問如何裝包,所得裝包總效益最大。演算法分析 最優子結構特性 0 1揹包的最優解具有最優子結構特性。與一般揹包問題...