恰好装满,表示空间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;
} 

结果是与上个表格的最后一行一致的。

posted on 2017-11-20 19:40  newbird2017  阅读(5664)  评论(0编辑  收藏  举报