分支界限法0-1背包问题

示例输入(规定物品数量为10,背包容量为50,输入为20个数,前十个为物品重量,后十个数为物品价值):

12
3
11
5
6
8
9
4
7
10
6
2
7
3
2
9
8
10
4
5
示例输出(最大价值):

44

根据我对算法书上的理解,自己瞎写出了以下代码,但是结果并不正确。不知具体哪里错了,还望大神指出。

先来说说我的理解吧。

分支界限法解决01背包问题:

1)   先求出每个物品的单位重量的价值,并按降序排序;

2)   按此顺序取物品,取或不取的时候都计算出上界:ub=cv+(bagw-cw)(value[i]/weight[i]),即(当前价值+最佳回报*剩余重量);

3)   比较两种情况下的上界ub,选择界限大的方式。前提是选取该物品后总重不会超过背包容量:bagw;

4)一个物品要么选,要么不选,选了就往选了的方式下继续分支,重复2,3,没选就往没选的方式下分支。

但是在计算的过程中,我发现,只要选择的情况下不超过总重量bagw就不会不选它。

分支界限法0-1背包问题

#include<stdio.h>

#include<iostream>

#include<queue>

using namespace std;

 

//bool select[10];//定义一个bool型数组用于判定是否选中对应物品;

int bagw=50,bagv,bestvalue,cw,cv;//背包可承受重量,背包可承受价值,最佳价值,当前重量,当前价值;

float ub;//上界;

//queue<thing> bestq;//定义一个结构体队列,用于存放最终结果;

struct avgvalue{//结构体存放物体的编号与单位重量的价值;

    int num;

    float avg;

    int value;//对应物品价值;

    int weight;//对应物品重量;

}re[10];

 

struct node{//定义结点;

    int cw;

    int cv;

    float ub;

}point[2];//point[0]表示左结点,[1]表示右结点;

 

void compare(avgvalue re[10])//排序物品单位重量的价值;

{

    int i,j,tmp;

    float t;

    for(i=0;i<=9;i++)

    {

       for(j=i+1;j<=9;j++)

        {

           if(re[i].avg<re[j].avg)

            {

               t=re[i].avg;

               re[i].avg=re[j].avg;

               re[j].avg=t;

               tmp=re[i].value;

               re[i].value=re[j].value;

               re[j].value=tmp;

               tmp=re[i].weight;

               re[i].weight=re[j].weight;

               re[j].weight=tmp;

            }

            else

               continue;

        }

    }

}

int der(avgvalue re1[10])//界限函数;

{

    int i,k,t;//j用来存放当前最大单位回报;

    float j;

    cw=0,cv=0;//初始化当前重量与价值;

    j=re[0].avg;

   ub=j*(bagw-cw)+cv;//上界公式,找到根节点;

    for(i=0;i<=8;i++)

    {

       j=re[i+1].avg;

       point[1].cv=cv;

       point[1].cw=cw;

        point[1].ub=j*(bagw-point[1].cw)+point[1].cv;//不包含第i个物品时当前最佳回报;

       point[0].cw=re1[i].weight;

       if(cw+point[0].cw<=bagw)//包含第i个物品不超重的情况下;

        {

           point[0].cv=re1[i].value;

           point[0].ub=j*(bagw-cw-point[0].cw)+point[0].cv+cv;//包含第i个物品时当前最佳回报;

 

           if(point[0].ub>point[1].ub)

            {

               ub=point[0].ub;

               cw+=point[0].cw;

               cv+=point[0].cv;

            }

            else

               ub=point[1].ub;

        }

        else//若包含超重,直接选择不包含的情况;

           ub=point[1].ub;

    }

    return cv;

}

 

int main()

{

    int i;

   for(i=0;i<=9;i++)

    {

       cin>>re[i].weight;//输入10个物品的重量;

    }

   for(i=0;i<=9;i++)

    {

       cin>>re[i].value;//输入10个物品的价值;

    }

    for(i=0;i<=9;i++)

    {

        re[i].num=i;

        re[i].avg=(float)re[i].value/re[i].weight;

    }

    compare(re);

   bestvalue=der(re);

   cout<<bestvalue<<endl;

    return 0;

}

分支界限法0-1背包问题