動態規劃之01揹包問題

2021-07-14 14:05:12 字數 4033 閱讀 1479

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揹包的最優解具有最優子結構特性。與一般揹包問題...