(九)分支限界法

2023-05-16


       分支限界法(branch and bound method)按广度优先策略搜索问题的解空间树,在搜索过程中,对待处理的节点根据限界函数估算目标函数的可能取值,从中选取使目标函数取得极值(极大或极小)的结点优先进行广度优先搜索,从而不断调整搜索方向,尽快找到问题的解。分支限界法适合求解最优化问题。



 1、分支限界法思想

       上节中回溯法是从根节点出发,按照深度优先的策略搜索问题的解空间树,在搜索过程中,如果某点所代表的部分解不满足约束条件,则对该节点为根的子树进行剪枝;否则继续按照深度优先的策略搜索以该结点为根,当搜索到一个满足的约束条件的叶子结点时,就找到了一个可行解。


       分支限界法首先要确定一个合理的限界函数(bound funciton),并根据限界函数确定目标函数的界[down ,up],按照广度优先策略搜索问题的解空间树,在分直结点上依次扩展该结点的孩子结点,分别估算孩子结点的目标函数可能值,如果某孩子结点的目标函数可能超出目标函数的界,则将其丢弃;否则将其加入待处理结点表(简称PT表),依次从表PT中选取使目标函数取得极值的结点成为当前扩展结点,重复上述过程,直到得到最优解。




2、TSP问题中使用分支限界法

       【TSP问题】:

       TSP问题是指旅行家要旅行n个城市,要求各个城市经理且仅经理依次然后回到出发城市,并要求所走的路程最短。我们以下图的无限图为例,采用分支限界法解决这个问题。




       该无向图对应的代价矩阵如下所示:


       代价矩阵是1到1,1到2,1到3,1到4,1到5距离写在第一行,第二行为2到1,2到2,2到3,2到4,、、、依次


       (1)找到目标函数的界。上界为,采用贪心算法求得上界,从节点1开始到节点3--->5--->4--->2--->1,路径,即为图中红色圈的路径,其路径长度为C=1+2+3+7+3=16。

下界为矩阵中每行中两个最小的相加,所有的行加起来的和的一半。( (3+1)+(3+6)+(1+2)+(3+4)+(2 +3) )/2=14 

所以求得界为[14,16]。

       (2)计算每个节点的限界值。

计算目标函数(限界函数),lb分为三部分,第一部分是经过路径的长度相加的2倍,加上第二部分离着路径首尾节点最近的距离相加(不在已知路径上的),加上第三部分除了路径上节点,矩阵中两个最短的距离相加,最后这三部分和相加,得到的结果除以2便是每个节点的限界值。

       (3)画出PT图。如下所示。





 

              根据上述所述得到最优解1-->3-->5-->4-->2-->1



【C代码】:

//分支限界法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define INF 100000
using namespace std;
/*  n*n的一个矩阵  */
int n;
int mp[22][22];//最少3个点,最多15个点
/*输入距离矩阵*/
void in()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j)
            {
                mp[i][j]=INF;
                continue;
            }
            scanf("%d",&mp[i][j]);
        }
    }
}
struct node
{
    int visp[22];//标记哪些点走了
    int st;//起点
    int st_p;//起点的邻接点
    int ed;//终点
    int ed_p;//终点的邻接点
    int k;//走过的点数
    int sumv;//经过路径的距离
    int lb;//目标函数的值
    bool operator <(const node &p )const
    {
        return lb>p.lb;
    }
};
priority_queue<node> q;
int low,up;
int inq[22];
//确定上界
int dfs(int u,int k,int l)
{
    if(k==n) return l+mp[u][1];
    int minlen=INF , p;
    for(int i=1; i<=n; i++)
    {
        if(inq[i]==0&&minlen>mp[u][i])/*取与所有点的连边中最小的边*/
        {
            minlen=mp[u][i];
            p=i;
        }
    }
    inq[p]=1;
    return dfs(p,k+1,l+minlen);
}
int get_lb(node p)
{
    int ret=p.sumv*2;//路径上的点的距离
    int min1=INF,min2=INF;//起点和终点连出来的边
    for(int i=1; i<=n; i++)
    {
        if(p.visp[i]==0&&min1>mp[i][p.st])
        {
            min1=mp[i][p.st];
        }
    }
    ret+=min1;
    for(int i=1; i<=n; i++)
    {
        if(p.visp[i]==0&&min2>mp[p.ed][i])
        {
            min2=mp[p.ed][i];
        }
    }
    ret+=min2;
    for(int i=1; i<=n; i++)
    {
        if(p.visp[i]==0)
        {
            min1=min2=INF;
            for(int j=1; j<=n; j++)
            {
                if(min1>mp[i][j])
                min1=mp[i][j];
            }
            for(int j=1; j<=n; j++)
            {
                if(min2>mp[j][i])
                min2=mp[j][i];
            }
            ret+=min1+min2;
        }
    }
    return ret%2==0?(ret/2):(ret/2+1);
}
void get_up()
{
    inq[1]=1;
    up=dfs(1,1,0);
}
void get_low()
{
    low=0;
    for(int i=1; i<=n; i++)
    {
        /*通过排序求两个最小值*/
        int min1=INF,min2=INF;
        int tmpA[22];
        for(int j=1; j<=n; j++)
        {
            tmpA[j]=mp[i][j];
        }
        sort(tmpA+1,tmpA+1+n);//对临时的数组进行排序
        low+=tmpA[1];
    }
}
int solve()
{
    /*贪心法确定上界*/
    get_up();
    
    /*取每行最小的边之和作为下界*/
    get_low();
    
    /*设置初始点,默认从1开始 */
    node star;
    star.st=1;
    star.ed=1;
    star.k=1;
    for(int i=1; i<=n; i++) star.visp[i]=0;
    star.visp[1]=1;
    star.sumv=0;
    star.lb=low;
    
    /*ret为问题的解*/
    int ret=INF;
    
    q.push(star);
    while(!q.empty())
    {
        node tmp=q.top();
        q.pop();
        if(tmp.k==n-1)
        {
            /*找最后一个没有走的点*/
            int p;
            for(int i=1; i<=n; i++)
            {
                if(tmp.visp[i]==0)
                {
                    p=i;
                    break;
                }
            }
            int ans=tmp.sumv+mp[p][tmp.st]+mp[tmp.ed][p];
            node judge = q.top();
            
            /*如果当前的路径和比所有的目标函数值都小则跳出*/
            if(ans <= judge.lb)
            {
                ret=min(ans,ret);
                break;
            }
            /*否则继续求其他可能的路径和,并更新上界*/
            else
            {
                up = min(up,ans);
                ret=min(ret,ans);
                continue;
            }
        }
        /*当前点可以向下扩展的点入优先级队列*/
        node next;
        for(int i=1; i<=n; i++)
        {
            if(tmp.visp[i]==0)
            {
                next.st=tmp.st;

                /*更新路径和*/
                next.sumv=tmp.sumv+mp[tmp.ed][i];

                /*更新最后一个点*/
                next.ed=i;

                /*更新顶点数*/
                next.k=tmp.k+1;

                /*更新经过的顶点*/
                for(int j=1; j<=n; j++) next.visp[j]=tmp.visp[j];
                next.visp[i]=1;

                /*求目标函数*/
                next.lb=get_lb(next);
                
                /*如果大于上界就不加入队列*/
                if(next.lb>up) continue;
                q.push(next);
            }
        }
    }
    return ret;
}
int main()
{
    in();
    printf("%d\n",solve());
    return 0;
}



3、分支限界法解决0/1背包问题。

       在这里只写个思路,相对来说也是比较简单的。

       (1)首先将背包按照价值由大到小进行排列。

       (2)找到上界和下界,背包问题的下界把第一个价值最大的装入背包。上界,采用背包问题的贪心算法(三种策略)最终求得上界。

       (3)限界函数ub=v+(W-w)*(v i+1    /    w i+1)

       (4)画PT表格,每个节点进行判断是否剪枝。最终得到最优解。



算法设计与分析大概总结到这。


       学习是一点一点深入的,这一点体会是多么的深刻,就像我的牙齿一样,黑的部分不是一天两天能黑的,牙疼的引起也不是一天两天的事情,要有牙齿病菌的这种精神!~~~





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(九)分支限界法 的相关文章

  • K8S中部署Grafana

    官方部署文档 xff1a Deploy Grafana on Kubernetes Grafana Labs 以下Yaml从官方copy下来的并做了些修改 xff0c Service使用Nodeport方式是为了便于本地访问 cat gra
  • 在 AlertManager 报警通知中展示监控图表

    参考原文档 xff1a 在 AlertManager 报警通知中展示监控图表 Promoter 是一个用于 AlertManager 通知的 Webhooks 实现 xff0c 支持在消息通知中展示实时报警图表 xff0c 也支持定制消息通
  • Github添加SSH keys

    问题 xff1a 在本地 xff08 linux系统 xff09 下载github仓库源代码时 xff0c 执行git clone 命令时出现以下报错 xff1a git clone git 64 github com hh hub pro
  • 阿里技术大牛最爱的“闲书”,你看过多少?

    在忙碌的写代码 修bug生活里 xff0c 你有多久没有闲下来 xff0c 读读 闲书 xff0c 取悦自己了呢 xff1f 正如梁文道所说 xff0c 读一些无用的书 xff0c 做一些无用的事 xff0c 花一些无用的时间 xff0c
  • blackbox_exporter 黑盒监测

    一 简介 blackbox exporter blackbox exporter是Prometheus 官方提供的 exporter 之一 xff0c 可以提供 http dns tcp icmp 的监控数据采集 xff0c blackbo
  • Python 与Django环境搭建

    系统 xff1a Windows 10 python环境搭建 1 python安装步骤 python包下载链接 xff1a https www python org downloads windows 下载版本 xff1a python 3
  • prometheus图

    Prometheus Server 框架图 xff0c 只要能提供对应的metrics接口 xff0c promehteus就能接入监控 xff0c prometheus会把抓取到的指标数据持久化到本地磁盘中 xff0c 跟其它数据库一样它
  • 经典文献阅读之--BEVDistill(BEV蒸馏)

    0 简介 之前作者前段时间在研究BEV的相关算法 xff0c 当时就觉得BEV算法好是好 xff0c 但是所需要的内存以及计算资源实在是太大了 xff0c 无法实时在真实场景中运行 我们知道多视图 xff08 multi view 三维目标
  • 经典文献阅读之--FastFlowNet(轻量光流估计)

    0 简介 密集的光流估计在许多机器人视觉任务中起着关键作用 随着深度学习的到来 xff0c 已经比传统方法以令人满意的精度预测了它 然而 xff0c 当前的网络经常占用大量参数并且需要沉重的计算成本 这些缺点阻碍了在功率或内存受限的移动设备
  • Matlab与ROS(1/2)---Message(三)

    0 简介 消息是ROS中交换数据的主要容器 主题和服务使用消息在节点之间传输数据 为了标识其数据结构 xff0c 每条消息都有一个消息类型 例如 xff0c 来自激光扫描仪的传感器数据通常以sensor msgs LaserScan类型的消
  • Matlab与ROS(1/2)---发布者和订阅者数据通信(四)

    0 简介 我们在前面一节介绍了Matlab与Message的通信 xff0c 而我们这一节主要来介绍发布者和订阅者在Matlab中的操作 这部分我们主要来看一下ROS1和ROS2中分别是如何使用Topic的 1 ROS1的消息订阅与发布 1
  • Matlab与ROS(1/2)---服务端和客户端数据通信(五)

    0 简介 在前几讲我们讲了Matlab中的Message以及Topic的相关知识 而ROS主要支持的通信机制还有服务这一类 服务通过允许请求以及响应的通信方式 xff0c 来给整个系统完成更紧密的耦合 服务客户端向服务服务器发送请求消息并等
  • Matlab与ROS---Action与Gazebo(六)

    0 简介 对于ROS1而言 xff0c 其在Matlab当中相较于ROS2还有一些比较高级的用法 xff0c 比如说我们接下来要说的Action和Gazebo仿真 1 ROS Action ROS的Action行为模式当中也存在有一个客户端
  • Matlab与ROS---TF坐标系(七)

    0 简介 我们上面讲了最基础的通信机制以及在Matlab中如何使用这些通信 xff0c 下面我们这一讲来主要介绍ROS当中最常用的TF坐标系在Matlab中的使用 tf是分布式的 xff0c 因此所有的坐标帧信息对ROS网络中的每个节点都是
  • OCR如何读取皱巴巴的文件?深度学习在文档图像形变矫正的应用详解

    阿里妹导读 xff1a OCR作为智能审核的重要环节 xff0c 其识别准确率影响着最终审核效果的好坏 xff0c 而来自扫描仪 智能手机的文档图像多存在卷曲 折叠 本文旨在利用深度学习算法对文档图像的形变进行矫正 xff0c 从而提高OC
  • 经典文献阅读之--VGICP(体素化的ICP匹配)

    0 简介 之前我们在以前的文章中介绍了很多有关于点云匹配相关的知识 xff0c 最近两年处理GICP这一大一统的ICP匹配方法以外 xff0c 还有一个工作对体素化和ICP这两者打起了心思 xff0c Voxelized GICP for
  • 经典文献阅读之--Orbeez-SLAM(单目稠密点云建图)

    0 简介 对于现在的VSLAM而言 xff0c 现在越来越多的工作开始聚焦于如何将深度学习结合到VSLAM当中 xff0c 而最近的这个工作就给出了一个比较合适的方法 Orbeez SLAM A Real time Monocular Vi
  • 经典文献阅读之--NORLAB-ICP(重力约束ICP)

    0 简介 最近几年IPC相关的文章也出了不少 xff0c 最近作者有看到了一篇比较有意思的ICP论文 Gravity constrained point cloud registration xff0c 这篇论文将传统的ICP考虑了重力因素
  • 常见的3d bounding box标注工具

    0 简介 对于3d bounding box而言 xff0c 近几年随着自动驾驶的火热 xff0c 其标注工具也日渐多了起来 xff0c 本篇文章不讲具体的算法 xff0c 这里主要聚焦于这些开源的3d bounding box标注工具 x
  • 经典文献阅读之--A Lifelong Learning Approach to Mobile Robot Navigation(终生学习轨迹导航)

    0 简介 终生学习作为近年来比较火的一种深度学习方式 xff0c 导航终身学习 LLfN 旨在解决标准导航问题的一种新变体 xff0c 在该问题中 xff0c 智能体在有限的内存预算下 xff0c 通过学习提高在线经验或跨环境的导航性能 而

随机推荐

  • 避免使用第三方工具完成电脑环境检测

    0 简介 在之前配置各种深度学习环境的时候经常需要先检测一下电脑的软硬件环境 xff0c 其实整个过程比较重复和固定 xff0c 所以我们是否有可能一键检测Python版本 PIP版本 Conda版本 CUDA版本 电脑系统 CPU核数 C
  • 经典文献阅读之--PCAccumulation(动态三维场景构建)

    0 简介 多波束激光雷达传感器 xff0c 常用于自动驾驶汽车和移动机器人 xff0c 获取三维范围扫描序列 xff08 帧 xff09 由于角度扫描分辨率有限和遮挡 xff0c 每帧只稀疏地覆盖场景 稀疏性限制了下游过程的性能 xff0c
  • Linux中的算法分离手段

    0 简介 参数分离对于绝大多数算法开发来说收益是非常大的 xff0c 因为我们都知道 xff0c 随着平台的更替 xff0c 很多时候如果说数据流和算法交叠在一起 xff08 即接口与实现合在一起 xff09 这将有可能会导致在迁移平台时候
  • 经典文献阅读之--Evaluation of Lidar-based 3D SLAM algorithms (激光SLAM性能比较)

    0 简介 我们在日常使用激光SLAM算法的时候 xff0c 常常会发现现有的算法只会和一些比较经典或者前作去进行比较 xff0c 很多时候我们更希望对主流的激光SLAM方法进行性能比较 之前作者转载过一篇文章 常见不同3D激光SLAM方案对
  • 经典文献阅读之--Bidirectional Camera-LiDAR Fusion(Camera-LiDAR双向融合新范式)

    0 简介 对于激光雷达和视觉摄像头而言 xff0c 两者之间的多模态融合都是非常重要的 xff0c 而本文 Learning Optical Flow and Scene Flow with Bidirectional Camera LiD
  • 十年一剑,阿里推荐与搜索引擎平台AI·OS首次公开!

    阿里妹导读 xff1a 9月28日 xff0c 阿里搜索迎来了十周年纪念日 久经考验的搜索与推荐平台 xff0c 支撑了淘宝 天猫 优酷乃至海外电商在内整个阿里集团的推荐与搜索的业务 xff0c 引导成交占据了集团GMV的绝大部分份额 随着
  • 嵌入式笔试面试题目系列(汇总)

    嵌入式笔试 一 进程与线程1 什么是进程 线程 xff0c 有什么区别 xff1f 2 多进程 多线程的优缺点3 什么时候用进程 xff0c 什么时候用线程4 多进程 多线程同步 xff08 通讯 xff09 的方法5 进程线程的状态转换图
  • 一文带你学习Chat GPT兼并了解国内镜像网站

    OpenAI近期发布聊天机器人模型ChatGPT xff0c 迅速出圈全网 它以对话方式进行交互 以更贴近人的对话方式与使用者互动 xff0c 可以回答问题 承认错误 挑战不正确的前提 拒绝不适当的请求 高质量的回答 上瘾式的交互体验 xf
  • 经典文献阅读之--Point-LIO(鲁棒高带宽激光惯性里程计)

    0 简介 在我们之前接触的算法中 xff0c 基本上都是要处理帧间雷达畸变的 xff0c 类似于VSLAM系统 xff0c 频率固定 xff08 例如10Hz 而实际上 xff0c 激光雷达点是按照不同的时间瞬间顺序采样的 xff0c 将这
  • 深度学习模型压缩方法概述

    一 xff0c 模型压缩技术概述 我们知道 xff0c 一定程度上 xff0c 网络越深 xff0c 参数越多 xff0c 模型也会越复杂 xff0c 但其最终效果也越好 xff0c 而模型压缩算法是旨在将一个庞大而复杂的大模型转化为一个精
  • [Err] [ModelDatabase.cc:] Unable to parse model.config for model

    問題 xff1a Err ModelDatabase cc 390 Unable to parse model config for model http gazebosim org models bin 4 dropping task E
  • kazam崩溃(dash)存留文件格式为.mux/movie,有效convert to MP4

    整理 xff1a How To Convert mux Kazam into mp4 Worked YouTube
  • 一个老外提供的google docs代码。 看着蛋疼..

    最近终于找到些google docs的实现相关文章与代码 xff0c 之前一直在gdocs上面挖掘 现在看到官方的描述感觉蛮亲切的 xff0c 活活 官网描述的google docs的实现思路 xff1a http googledocs b
  • 详解各种iou损失函数的计算方式(iou、giou、ciou、diou)

    本文主要是理解各个回归损失函数的区别和改进 xff0c 其实最主要的还是这些损失函数在yolo中起到了非常大的作用 xff0c 包括从最原始的yolov3中引入 xff0c 到v4 v5中变成真正的官方损失函数 xff0c 确实很有效 本文
  • 1.机器视觉标准框架学习

    在工业机器视觉上 xff0c 常见的图像处理库有opencv halcon visionpro sherlcok等 其中visionpro和sherlcok是拖拽式编程 xff0c 方便用户开发视觉项目 但对于opencv 和halcon则
  • 我的2013,我的回归本质

    以前每到年头年尾总是要求自己要写年度总结 xff0c 写年度计划 xff0c 但到后面都不了了之了 xff0c 想起都觉得惭愧 我是一个大专生 xff0c 专业是电子信息工程 现在大三了 xff0c 感触良多 给自己的大学打个分吧 xff0
  • 二进制的浪漫

    0 基本性质 0 1 交换律 相同运算符下可任意交换 xff0c 不同的运算符不可交换 0 2 结合律 相同运算符是可结合的 0 3 分配律 a amp b
  • 安全多方计算新突破!阿里首次实现“公开可验证” 的安全方案

    阿里妹导读 xff1a 近日 xff0c 阿里安全双子座实验室与马里兰大学等高校合作的论文 Covert Security with Public Verifiability Faster Leaner and Simpler 1 被欧洲密
  • 书--益友--从不孤单

    看看自己的豆瓣读书 想读79 想读的书太多 xff0c 但工作会让读书变成一件奢侈的事情 xff0c 不过庆幸还是有奢侈的时间的 读书让我们快乐 雨果说过 xff0c 书籍是造就灵魂的工具 不知道你和我是否有相同的感受 读书能让我们开心 读
  • (九)分支限界法

    分支限界法 xff08 branch and bound method xff09 按广度优先策略搜索问题的解空间树 xff0c 在搜索过程中 xff0c 对待处理的节点根据限界函数估算目标函数的可能取值 xff0c 从中选取使目标函数取得