算法设计与分析——分支限界法
文章目录
- 1. 分支界限法
- 1.1 基本思想
- 1.2 搜索策略
- 1.3 队列式
- 1.4* 优先队列式
- 2. 典型案例
- 2.1 装载问题
- 2.1.1 问题描述
- 2.1.2 约束函数和限界条件
- 2.1.3 队列式分支界限法求解(案例解释)
- 2.1.4 案列二
- 2.1. 代码实现
- 2.2 0-1背包问题(基于优先队列)
- 2.2.1 队列的进出过程
- 2.2.2 上界值的计算
- 3. 回溯法与分支限界法异同
- c++中 friend的用法
1. 分支界限法
1.1 基本思想
对有约束条件的最优化问题的所有可行解(数目有限)空间进行搜索。该算法在具体执行时,把全部可行的解空间不断分割为越来越小的子集(称为分支),并为每个子集内的解的值计算一个下界或上界(称为界限)。在每次分支后,对凡是界限超出已知可行解值的那些子集不在做进一步分支。这样就缩小了搜索范围。这一过程一直进行到找出可行解为止,该可行解的值不大于任何子集的界限。
1.2 搜索策略
在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。为了有效地选择下一扩展结点,加速搜索的进程,在每一个活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。
1.3 队列式
按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
1.4* 优先队列式
按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。
2. 典型案例
2.1 装载问题
2.1.1 问题描述
集装箱装载问题要求确定在不超过轮船载重量的前提下,将尽可能多的集装箱装上轮船。
2.1.2 约束函数和限界条件
约束函数:当 Ew+wi > c 对扩展结点的左子树剪枝
限界函数:当 Ew+r <= bestw 对扩展结点的右子树剪枝
2.1.3 队列式分支界限法求解(案例解释)
轮船的载重量为c=80、集装箱个数n=4、重量分别为18 7 25 36。
定义一个先进先出(FIFO)队列Q,初始化队列时,在尾部增加一个 -1 标记。这是一个分层的标志,当一层结束时,在队列尾部增加一个 -1 标志。
定义扩展结点相应的载重量为Ew,剩余集装箱的重量为r,当前最优载重量为bestw。
没到一个结点就要计算bestw、r、Ew,然后进行约束函数和限界函数的判断,如果不满足约束函数则对左子树剪枝,不满足限界函数对右子树进行剪枝。例如下图中的结点M,此时bestw=50,r=7+36=43,r<bestw,则结点M不入队。结点O也是同样。
2.1.4 案列二
- 基于队列式的分支限界法解决
2.1. 代码实现
#include "iostream"
#include "queue"
using namespace std;#define NUM 100
int n; //集装箱的数量
int c; //轮船的载重量
int w[NUM]; //集装箱的重量数组int MaxLoading()
{queue<int> Q;Q.push(-1);int i = 0;int Ew = 0;int bestw = 0;int r = 0;for(int j=1; j<n; j++)r += w[j];//搜索子空间树while (true) {//检查左子树int wt = Ew + w[i];if (wt <= c) { //检查约束条件if (wt > bestw) bestw = wt;//加入活结点队列if (i < n - 1) Q.push(wt);}//检查右子树//检查上界条件if (Ew + r > bestw && i < n - 1)Q.push(Ew);//从队列中取出活结点Ew = Q.front();Q.pop();if (Ew == -1) { //判断同层的尾部if (Q.empty()) return bestw;//同层结点尾部标志Q.push(-1);//从队列中取出活结点Ew = Q.front();Q.pop();i++;r -= w[i];}}return bestw;
}
int main(){cin >> c;cin >> n;for (int i = 0; i < n; ++i) {cin >> w[i];}cout << MaxLoading();return 0;
}
2.2 0-1背包问题(基于优先队列)
2.2.1 队列的进出过程
每到一个结点就计算其上界,判断该上界值是否小于当前最优解,如果小于就减去,如果不小于就按照优先级(上界大小),按次序插入队列。
2.2.2 上界值的计算
采用 贪心算法 计算结点的上界值:将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包时的价值。
3. 回溯法与分支限界法异同
- 相同点:
都是一种在问题的解空间树T中搜索问题解的算法。
- 不同点:
(1)求解目标不同
(2)搜索方式不同
(3)对扩展结点的扩展方式不同
(4)存储空间的要求不同
搜索方式 | 求解目标 | 扩展方式 | 存储空间 | |
---|---|---|---|---|
回溯法 | 深度优先 | 满足条件的所有解 | 当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。 | 栈 |
分支限界法 | 广度优先 | 满足条件一个解或者特定意义的最优解 | 每个结点只有一次成为活结点的机会一旦成为扩展结点,就一次性产生所有儿子结点,并舍弃不可行解或非最优解的子结点。 | 队列、优先队列 |
c++中 friend的用法
- 普通的非成员函数友元
这类友元函数最常见,通常是操作符。
- 类作为友元
类作为友元需要注意的是友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件。但是在原始类的定义中(包含友元类声明的那个类),就不需要包含友元类的头文件.
另外,不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明。
- 类成员函数作为友元函数
这个稍微有点复杂,因为你要类成员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。
friend用法参考链接
员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。
friend用法参考链接
算法设计与分析——分支限界法相关推荐
- 算法设计与分析——分支限界法——n皇后问题
一.问题描述 问题描述:在nn格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n皇后问题等价于在n*n的棋盘上放置n个皇后,任何2个皇后 ...
- 算法设计与分析-分支限界法习题
7-1 布线问题 印刷电路板将布线区域划分成 n×m 个方格阵列,要求确定连接方格阵列中的方格a 点到方格b 的最短布线方案.在布线时,电路只能沿直线布线,为了避免线路相交,已布了线的方格做了封锁标记 ...
- 算法设计与分析—分支限界法应用(头歌实验)
第1关:装载问题 (FIFO 优先队列法) 问题描述 有一批共个集装箱要装上 2 艘载重量分别为 C1 和 C2 的轮船,其中集 装箱 i 的重量为 Wi ,且 装载问题要求确定是否有一个合理的装载方 ...
- 算法设计与分析——分支限界法——装载问题
有一批共个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为Wi,且装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船.如果有,找出一种装载方案. 容易证明:如果一个 ...
- 算法设计与分析之分支限界法
文章目录 前言 一.分支限界法概述 二.分支限界法的基本思想 三.分支限界法的基本过程 四.常见的两种分支限界法 五.应用分支限界法应注意的关键问题 六.分支限界法示例 总结 前言 大家好,越努力,越 ...
- 算法设计与分析——算法思想总结
算法设计与分析 1.分治法 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同.递归的解这些子问题,然后将各子问题的解合并得到原问题的解. 分治法所能解 ...
- 计算机算法设计与分析考试题,《计算机算法设计与分析》习题及答案
<计算机算法设计与分析>习题及答案 一.选择题 1.二分搜索算法是利用( A )实现的算法. A.分治策略 B.动态规划法 C.贪心法 D.回溯法 2.下列不是动态规划算法基本步骤的是( ...
- 计算机算法设计与分析教学大纲,《算法设计与分析》教学大纲
<<算法设计与分析>教学大纲>由会员分享,可在线阅读,更多相关<<算法设计与分析>教学大纲(3页珍藏版)>请在人人文库网上搜索. 1.课程编号:&quo ...
- 【算法设计与分析】经典常考三十三道例题AC代码
❥小虾目前大三,我校在大一下开设<数据结构>这门课,大二上开了<算法设计与分析>这门课,很庆幸这两门课的上机考试总成绩一门100,一门99,最后总分也都90+.下文会给出机试的 ...
最新文章
- fileinput_open_读写文件_python
- Android面试题目之(11) Class结构,动态代理和方法监控
- 脑残式网络编程入门(三):HTTP协议必知必会的一些知识
- Java数据结构与算法:二叉树
- 在项目里交叉使用Swift和OC
- 在SAP C4C TI(Thing Inspector)页面里添加自定义UI
- html中怎么选择相同的代码,不同的HTML,相同的代码隐藏和相同的控件
- 完整的Android 新浪微博api调用DEMO
- 李宏毅机器学习(八)自编码器(Auto-encoder)
- 计算机控制系统EHA,优·计算机控制技术第四章.doc
- 【小记录】关于dojo中的on事件
- 极速还原 V4.0 简体中文绿色免费版
- r730 raid5 linux 驱动,Dell power edge R730 raid卡安装配置
- python中的head函数_Pandas DataFrame.head()用法例子
- HttpServletRequest请求中获取操作系统,浏览器及浏览器版本信息
- 字节跳动杨震原:A/B测试不是万能的,但不会一定不行 ​
- 求最大公约数和最小公倍数的方法:
- Python中如何读取npy、npz文件?
- c语言:已知斐波那契数列定义:f(0) = 0; f(1) = 1;f(n) = f(n-1) + f(n-2);请计算并输出数列的前n(n<=30)项。
- 杰理-watch-手表-AC701-双击屏幕唤醒