01背包問題(二)恰好裝滿的情形


恰好裝滿,表示空間V完全被占用。

之前的題目是說,在不超過空間V的情況下,使價值最大化。

 

現在考慮動態規划的初始值問題。

在前一個問題中,dp[i][v]初始化設置為0.

因為在初始狀態,背包中沒有任何物品。不論背包的容量多大,里面的價值只是0.這個狀態是合法的。因為背包並沒有超出容量。

 

現在,背包只有完全占滿才是合法的值。那么在初始狀態,dp[i][0]=0是合法的,因為容量為0,不放任何東西就是合法了。

其他的都是非法值。應該設置為負無窮。

const int INF = 0x3f3f3f3f;
const int NINF= -INF - 1;
int main()
{
    int n = 5;
    int sum = 12;

    int w[5] = {5, 4, 7 ,2 ,6};
    int p[5] = {12,3,10, 3, 6};

    int dp[6][13];

    int i,v;

    memset(dp,NINF,sizeof(dp));
    dp[0][0] = 0;

    for(i = 1; i <= n ; i++)
    {
        dp[i][0] = 0;
        
        for(v = 1;v <= sum; v++)
        {
            if(v >= w[i-1])    dp[i][v] = max_2( dp[i-1][v-w[i-1]] + p[i-1],dp[i-1][v] );
            else            dp[i][v] = dp[i-1][v];
        }
    }
    
     for(i = 1; i <= n ; i++)
    {
        for(v = 0;v<=sum;v++)
        {
            if(dp[i][v] < 0)
                printf("X  ");
            else
                printf("%d  ",dp[i][v]);
        }
        printf("\n");
    }
    return 0;
}

運行結果如下:

可以看到,背包容量為0時,總有合法值。因為只要不放就是合法的。

容量為1時,由於沒有體積為1的物品,所以v=1的所有狀態都是非法的。取值為負無窮。

V=2時,由於物品4的體積為2,所以前4件 和 前5件,都有合法值。

以此類推。

 

空間優化后使用一維數組的代碼:

int main()
{
    int w[5] = {5, 4, 7 ,2 ,6};
    int p[5] = {12,3,10, 3, 6};

    int i,v,n = 5;
    int sum = 12;

    int dp[13];

    memset(dp,NINF,sizeof(dp));
    dp[0] = 0;
    for(i=0;i<n;i++)
    {
        for(v=sum;v>=w[i];v--)        //   v不夠w[i]的話,dp[v]不會改變。
        {
            dp[v] = max_2( dp[v], dp[v-w[i]]+p[i] );
        }
    }

    for(i = 0;i<=sum;i++)
    {
        printf("%d ",dp[i]);
    }
    return 0;
} 

結果是與上個表格的最后一行一致的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM