0/1背包问题:

问题描述:

现有n种物品,对1<=i<=n,已知第i种物品的重量为正整数Wi,价值为正整数Vi,背包能承受的最大载重量为正整数W,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过W且总价值尽量大。(注意:这里对每种物品或者全取或者一点都不取,不允许只取一部分)。

算法分析:

1..实现的目标:使得子集中物品的总重量不超过W且总价值尽量大。

2.限制的条件:包最大载重量是一定的,物品的个数是一定的。

3.实现的过程:对每种物品进行舍取。

4.实现的方法:递归。


对于第n个物品来说,我们对它有两种处理方式。

1.  放到背包中,我们用x[n]=1表示。

2.  由于条件限制,不能放到背包中,用x[n]=0表示。

重新审视一下,我们会发现,对这个物品处理完后,我们会发现我们遇到了相似的问题

1.  若物品放到了背包中,我们的任务变为:现在变成了有n-1种物品,背包能承受的最大载重量为正整数W-Wi,找到最优解。

2.  若物品没有放到背包中,我们的任务变为:现在变成了有n-1种物品,背包能承受的最大载重量为正整数W,找到最优解。

 

证明结论:

设函数KnapSack(n,m)来表示从n个物品中,背包的最大承重是m的条件限制下的最好方案的值 根据上述的两种情况我们可以列出下列等式:


递归调用的终结条件是背包的容量为0或物品的数量为0

下面我们来看看限制条件:

为什么我们会不选那个物品呢?因为选了它就不会得到最大值。就是说,

KnapSack(n,m)>KnapSack(n-1,m-Wn)+Vn;

程序实现:

intMake(int i, int j) 

{   

    int r1 = 0; 

    int r2 = 0; 

    int r = 0;

    if (i == -1) 

    { 

        return 0; 

    }

    if(j >= WEIGHT[i])   //背包剩余空间可以放下物品 i   

    { 

        r1 = Make(i-1,j - WEIGHT[i]) +VALUE[i]; //第i件物品放入所能得到的价值 

        r2 = Make(i-1,j); //第i件物品不放所能得到的价值   

        r = (r1>r2)?r1:r2; 

    } 

    return r; 

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值