分支界定法(branch and bound)与背包问题的代码实现

分支界定法(branch and bound)与背包问题的代码实现


不卖茶的吴龙茗茶

分支界定法是一种在整数规划中常用的算法,其主要思想为将大问题分割成小问题进行求解。分支界定法是围绕着一个二叉树进行的,以背包问题为例:

假设小明有一个背包,其总的容积为30,小明有三件东西可以带,三件东西的体积分别为:10,15,20。求问小明如何能够在背包中装下更大体积的物品?

我们建立一个长度为三的数组,元素大小分别为10,15,20。然后利用二叉树帮助我们解决问题

一个满二叉树应该是如下图所示
在这里插入图片描述

我们首先根据是否将第一个物品放入背包中进行分类(在这个二叉树中,左孩子一律为放入背包,右孩子一律为不放入背包),然后讨论第二个物品是否放入背包,以此类推。圆圈中的数字表明了放入背包的东西的总体积。

但是在分支界定法中引入了剪枝的操作,也就是在创造二叉树时,我们会对节点进行判断,如果节点的值加上剩余能够装载的物品体积小于当前的最大装载量,那么我们就对该节点进行剪枝,即在二叉树中不生成此节点。进行了剪枝之后的二叉树如下如图所示:
在这里插入图片描述

红色部分为被剪枝的部分。

FIFO分支界定法求解背包问题(c++实现):

#include <iostream>
#include <list>
#include "limits.h"
using namespace std;

int main(){
    int best =0; int depth = 0;
    int par_val = 0; int cur_val = 0;
    int capacity = 30;
    int box[] = {10,15,20};
    list<int> myqueue;
    myqueue.push_back(0);
    //sizeof(box)/sizeof(box[0]为数组box的长度,在这里为3
    while(depth < sizeof(box)/sizeof(box[0]) && myqueue.size() != 0 ){
        //check left child
        par_val = myqueue.front();
        cur_val = par_val + box[depth];
        if(cur_val > best && cur_val <= capacity){
            best = cur_val;
        }
        myqueue.push_back(cur_val);

        //check right child
        cur_val = par_val;
        int rest = cur_val; 
        //判断余下的体积和现在算出来的best哪个大
        for(int i = depth + 1; i < sizeof(box)/sizeof(box[0]); i++){
            rest += box[i];
        }
        //剪枝判断,如果进行剪枝则加入一个负无穷,方便判断该层是否结束
        if(best < rest){
            myqueue.push_back(cur_val);
        }else{
            myqueue.push_back(INT_MIN);
        }
        myqueue.pop_front();
        //根据是否为2^n来判断该层是否结束
        if( (myqueue.size() & myqueue.size() - 1) == 0){
            depth++;
        }
    }
    cout << "best: " << best <<"\n";
}

运行结果:

在这里插入图片描述

Reference:

①:https://blog.csdn.net/yinlili2010/article/details/39313035

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值