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

分支限界法是以广度优先遍历,可以用队列实现,附详细代码

#include <bits/stdc++.h>
using namespace std;
int Weight[100];//物品重量
int Value[100];//物品价值
int N;//总的物品数量
int n=-1;//创造树标记
int max_value=INT_MIN;//当前得出最大价值;
int max_weight;//背包限制的重量
struct A* max_pointer;//值最大时的节点
struct A* D[10000];//队列数组
struct A
{
    struct A *lchild;//左节点
    struct A *rchild;//右节点
    struct A *parent;
    int flag;//查询用到0表示没放入,1表示放入
    int value;//节点价值
    int weight;//节点重量

};
void createtree(struct A *B)//创造树,重点
{
    n++;//代表相应的物品
    if(n<N)
    {
        B->lchild=new(struct A)();//左节点表示不放入
        B->lchild->value=B->value;//与父节点价值相等
        B->lchild->weight=B->weight;//与父节点重量相等
        B->lchild->flag=0;//表示没放入该物品
        B->lchild->parent=B;//标记父母
        createtree(B->lchild);//递归建树
        n--;
        B->rchild=(struct A*)malloc(sizeof(struct A));//右节点表示放入
        B->rchild->value=B->value+Value[n];//价值为父节点价值+物品价值;
        B->rchild->weight=B->weight+Weight[n];//重量为父节点重量+物品重量;
        B->rchild->flag=1;//表示放入该物品
        B->rchild->parent=B;//标记父母
        createtree(B->rchild);//递归建树
        n--;

    }
    else
    {
        B->lchild=NULL;
        B->rchild=NULL;
    }
}
void print(struct A*head)//可以用来查看树的结构
{  int a;
  if(N>0)//刚好N可以表示层数,head->flag表示该节点有没有选中
  { a=N;
    N--;
    print(head->parent);
    if(head->flag==1)//表示选中
    cout<<a<<" ";
  }
}

int main()
{
    struct A* head;//根节点
    head=(struct A*)malloc(sizeof(struct A));//分配空间
    head->parent=NULL;
    head->value=0;//价值初始化
    head->weight=0;//重量初始化
    cout<<"请输入背包容积:";
    cin>>max_weight;//背包容积
    cout<<"请输入物品数量:";
    cin>>N;//物品数
    cout<<"请输入各个物品的重量:";
    for(int i=0; i<N; i++) //物品重量输入
    {
        cin>>Weight[i];
    }
    cout<<"请输入各个物品的价值:";
    for(int i=0; i<N; i++) //物品价值输入
    {
        cin>>Value[i];
    }
    createtree(head);//创造树
    int begin=0,end=0;//队列的头标记,尾标记
    D[0]=head;
    end++;//
    while(begin!=end)//空队列
    {
        if(D[begin]->value>=max_value)//更新最大价值
        {
            max_value=D[begin]->value;//记录最大值
            max_pointer=D[begin];//记录该节点
        }

        if(D[begin]->lchild&&D[begin]->lchild->weight<=max_weight)//入队列,可以放入剪枝条件
        {
            D[end]=D[begin]->lchild;
            end++;
        }
        if(D[begin]->rchild&&D[begin]->rchild->weight<=max_weight)//入队列,可以放入剪枝条件
        {
            D[end]=D[begin]->rchild;
            end++;
        }
        begin++;//头标记向后走
    }
    cout<<max_value<<endl;//输出结果
    print(max_pointer);

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值