動態規劃問題一:揹包問題
阿新 • • 發佈:2018-11-30
學習自:Christal_R
有一個揹包,能盛放的物品總重量為capacity,設有number件物品,其重量分別為w1,w2,…,wn,希看從N件物品中選擇若干物品,所選物品的重量之和恰能放進該揹包,即所選物品的重量之和即是S。
尋找遞推關係式,面對當前商品有兩種可能性:
第一,包的容量比該商品體積小,裝不下,此時的價值與前i-1個的價值是一樣的,即V(i,j)=V(i-1,j);
第二,還有足夠的容量可以裝該商品,但裝了也不一定達到當前最優價值,所以在裝與不裝之間選擇最優的一個,即V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) },其中V(i-1,j)表示不裝,V(i-1,j-w(i))+v(i) 表示裝了第i個商品,揹包容量減少w(i)但價值增加了v(i);
由此可以得出遞推關係式:
- j<w(i) V(i,j)=V(i-1,j)
- j>=w(i) V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }
void FindMax()//動態規劃
{
int i,j;
//填表
for(i=1;i<=number;i++)
{
for(j=1;j<=capacity;j++)
{
if(j<w[i])//包裝不進
{
V[i][j]= V[i-1][j];
}
else//能裝
{
if(V[i-1][j]>V[i-1][j-w[i]]+v[i])//不裝價值大
{
V[i][j]=V[i-1][j];
}
else//前i-1個物品的最優解與第i個物品的價值之和更大
{
V[i][j]=V[i-1][j-w[i]]+v[i] ;
}
}
}
}
}
表格填完,最優解即是V(number,capacity)=V(4,8)=10,但還不知道解由哪些商品組成,故要根據最優解回溯找出解的組成,根據填表的原理可以有如下的尋解方式:
- V(i,j)=V(i-1,j)時,說明沒有選擇第i 個商品,則回到V(i-1,j);
- V(i,j)=V(i-1,j-w(i))+v(i)實時,說明裝了第i個商品,該商品是最優解組成一部分,隨後我們得回到裝該商品之前,即回到V(i-1,j-w(i));
- 一直遍歷到i=0結束為止,所有解的組成都會找到。
void FindWhat(int i,int j)//尋找解的組成方式
{
if(i>=0)
{
if(V[i][j]==V[i-1][j])//相等說明沒裝
{
item[i]=0;//全域性變數,標記未被選中
FindWhat(i-1,j);
}
else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
{
item[i]=1;//標記已被選中
FindWhat(i-1,j-w[i]);//回到裝包之前的位置
}
}
}