01背包图解
01背包問(wèn)題描述:一個(gè)旅行者有一個(gè)最多能用M公斤的背包,現(xiàn)在有N件物品,
它們的重量分別是W1,W2,...,Wn,
它們的價(jià)值分別為P1,P2,...,Pn.
若每種物品只有一件求旅行者能獲得最大總價(jià)值。
?
方式一:遍歷M*N的數(shù)組,對(duì)應(yīng)下圖包的總?cè)萘縈=20,物品種類數(shù)N=5
代碼如下:
const int nRes=5;//5種物品
int nResWeight[nRes+1]={0,5,3,4,7,8};//每種物品對(duì)應(yīng)重量
int nResValue[nRes+1]={0,14,6,9,18,20};//每種物品對(duì)應(yīng)價(jià)值
const int nTotleW=20;//背包容量為20
int nValueTable[nRes+1][nTotleW+1]={0};//動(dòng)態(tài)價(jià)值表,每一項(xiàng)對(duì)應(yīng)包當(dāng)前所能裝入的最優(yōu)值
int KitBag()
{
for(int i=1;i<=nRes;i++)
for(int j=1;j<=nTotleW;j++)//包容量逐漸遞增
{
if(j>=nResWeight[i]) //當(dāng)包容量大于等于當(dāng)前物品重時(shí)
{//如果裝入當(dāng)前物品所能達(dá)最大價(jià)值>不裝當(dāng)前物品,包選裝前面物品所能獲得的最大價(jià)值
//裝入當(dāng)前物品所能達(dá)最大價(jià)值=當(dāng)前物品價(jià)值+當(dāng)前包容量j扣除當(dāng)前物品重量后,剩余的容量所能裝入的最大價(jià)值。
//對(duì)照上表,當(dāng)遍歷到i=2,j=8時(shí),nValueTable[i-1][j-nResWeight[i]]=nValueTable[1][5]=14,滿足條件就裝入物品。
?if(nResValue[i]+nValueTable[i-1][j-nResWeight[i]]>nValueTable[i-1][j])
nValueTable[i][j]=nResValue[i]+nValueTable[i-1][j-nResWeight[i]];//當(dāng)前物品裝入包.
?else//當(dāng)前物品不裝入包,當(dāng)前包容量下的最大價(jià)值仍然是原來(lái)的價(jià)值
nValueTable[i][j]=nValueTable[i-1][j];
}
else//包容量不足以裝入當(dāng)前物品時(shí),沿用原來(lái)的包容量最大價(jià)值
nValueTable[i][j]=nValueTable[i-1][j];
??}
cout<<"最大值為:"<<nValueTable[nRes][nTotleW];
return nValueTable[nRes][nTotleW];
?};
方式二:采用遞歸方式,遍歷二叉樹(shù),并通過(guò)映射表來(lái)剪枝。
代碼如下:
int RecursionBag(int nR,int nW)//傳入資源數(shù),包容量
{
if(nR==0||nW==0){
return 0;
}
if(nValueTable[nR][nW]!=0){
//當(dāng)前節(jié)點(diǎn)是已訪問(wèn)過(guò)的節(jié)點(diǎn),直接返回存儲(chǔ)的最優(yōu)值
return nValueTable[nR][nW];
}
if(nW>=nResWeight[nR])//包容量大于等于當(dāng)前物品重
{//獲得物品放入和不放入兩種情況中的價(jià)值最大者
nValueTable[nR][nW]=max(nResValue[nR]+RecursionBag(nR-1,nW-nResWeight[nR]),//物品入包后的價(jià)值
RecursionBag(nR-1,nW));//物品不入包的最大價(jià)值
}
else//包容量不足以放入當(dāng)前物品
nValueTable[nR][nW]=RecursionBag(nR-1,nW);
return nValueTable[nR][nW];
}
對(duì)比兩種方式可知,第二種方式遍歷的數(shù)據(jù)量為黃色標(biāo)注結(jié)點(diǎn),要小于第一種方式的數(shù)據(jù)訪問(wèn)量。
不過(guò)當(dāng)節(jié)點(diǎn)深度上千后,如果包容量遠(yuǎn)小2^n,比如為 10000,這時(shí)前一種方法要快得多。估計(jì)這時(shí),遞歸對(duì)訪問(wèn)過(guò)的節(jié)點(diǎn)雖然不再訪問(wèn)它的子節(jié)點(diǎn),但是這樣重復(fù)訪問(wèn)到的父節(jié)點(diǎn)數(shù)量過(guò)于龐大。
總結(jié)
- 上一篇: CentOS 下 rpm包与 yum 安
- 下一篇: 动态规划 最短路径