zeroOnePack

01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大。

        动态规划(DP):

        1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值。

        2) 根据第i件物品放或不放进行决策

                         

        其中F[i-1][j]表示前i-1件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值;

        而F[i-1][j-C[i]]+W[i]表示前i-1件物品中选取若干件物品放入剩余空间为j-C[i]的背包中所能取得的最大价值加上第i件物品的价值。

        根据第i件物品放或是不放确定遍历到第i件物品时的状态F[i][j]。

        设物品件数为N,背包容量为V,第i件物品体积为C[i],第i件物品价值为W[i]。

 

在0/1背包问题中,物体或者被装入背包,或者不被装入背包,只有两种选择。
                      
         循环变量i,j意义:前i个物品能够装入载重量为j的背包中
         (n+1)*(m+1)数组value意义:value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值
         若w[i]>j,第i个物品不装入背包
         否则,若w[i]<=j且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值(替换为第i个物品装入背包后的价值)
          
          计算最大价值的动态规划算法如下:
                             
     // 计算
     for (i = 1 ;i < row;i ++ )
    
... {
        
for(j=1;j<col;j++)
        
...{
            
//w[i]>j,第i个物品不装入背包
            value[i][j]=value[i-1][j];
            
//w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值
            int temp=value[i-1][j-w[i]]+v[i];
            
if(w[i]<=&& temp>value[i][j])
                value[i][j]
=temp;
        }

    }
                             
      即该段程序完成以下n个阶段:
     1:只装入1个物品,确定在各种不同载重量的背包下,能够得到的最大价值
     2:装入2个物品,确定在各种不同载重量的背包下,能够得到的最大价值
     。。。
     n:以此类推,装入n个物品,确定在各种不同载重量的背包下,能够得到的最大价值      

3. 问题求解

      确定装入背包的具体物品,从value[n][m]向前逆推:
           若value[n][m]>value[n-1][m],则第n个物品被装入背包,且前n-1个物品被装入载重量为m-w[n]的背包中
           否则,第n个物品没有装入背包,且前n-1个物品被装入载重量为m的背包中
      以此类推,直到确定第一个物品是否被装入背包为止。逆推代码如下:

              

    //逆推求装入的物品
    j=m;
    
for(i=row-1;i>0;i--)
    
...{
        
if(value[i][j]>value[i-1][j])
        
...{
            c[i]
=1;
            j
-=w[i];
        }

    }

 

#include <stdio.h>

int main()
{
    int i;    // size  of current item
    int k;    // value of current item
    
    int num =  6;        // number   of items
    int cap = 10;        // capacity of our bag
    int size[]  = {-9999, 2, 3, 1, 4, 6, 5 };       // size  of each item
    int value[] = {-9999, 5, 6, 5, 1, 19, 7 };       // value of each item
    
    // array of results
    int F[num + 1][cap + 1];
    
    // initialize first row and first col
    for (i = 0; i <= cap; ++i)
        F[0][i] = 0;
    for (i = 1; i <= num; ++i)
        F[i][0] = 0;
    
    // dynamic programming for zeroOneBag problem
    for (i = 1; i <= num; ++i)
    {
        for (k = 1; k <= cap; ++k)
        {
            F[i][k] = F[i-1][k];
            if ( k >= size[i] && F[i-1][k-size[i]]+value[i] > F[i][k] )
                F[i][k] = F[i-1][k-size[i]]+value[i];
        }
    }
    
    // print result array
    for (i = 1; i <= num; ++i)
    {
        for (k = 1; k <= cap; ++k)
           printf("%3d ", F[i][k]);
        printf("\n");
    }
    printf("max value = %d\n\n",  F[num][cap]);
    
    // print choose items
    k = cap;
    for (i = num; i > 0; --i)
    {
        if(F[i][k] > F[i-1][k])
        {
            printf("item: %d choosed, size: %d, value: %d\n", i, size[i], value[i]);
            k -= size[i];
        }
    }
    
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值