1. 程式人生 > >動態規劃問題一:揹包問題

動態規劃問題一:揹包問題

學習自: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);

由此可以得出遞推關係式:

  1. j<w(i) V(i,j)=V(i-1,j)
  2. 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,但還不知道解由哪些商品組成,故要根據最優解回溯找出解的組成,根據填表的原理可以有如下的尋解方式:

  1. V(i,j)=V(i-1,j)時,說明沒有選擇第i 個商品,則回到V(i-1,j);
  2. V(i,j)=V(i-1,j-w(i))+v(i)實時,說明裝了第i個商品,該商品是最優解組成一部分,隨後我們得回到裝該商品之前,即回到V(i-1,j-w(i));
  3. 一直遍歷到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]);//回到裝包之前的位置
        }
    }
}