第6章 分支限界法(1-例子)
第6章 分支限界法

通常采用最大堆或最小堆来实现优先队列式分支限界法求解问 题。
可以用如下方法求得最优解中的分量:1)对每个扩展结点保存
该结点到根结点的路径;2)在搜索过程中构建搜索经过的树结
构,在求得最优解时,从叶子结点不断回溯到根结点,以确定最
优202解0年中7月的19日各个分量。
21
提纲
一、分支限界法的基本思想 二、单源最短路径问题 三、装载问题 四、0-1背包问题 五、最大团问题 六、旅行售货员问题
E 使总的路程最短。
23
F GH I J K 43 42 32
L MN O P Q
2020年7月19日
17
分支限界法解旅行售货员问题
FIFO队列:
活结点队列: {{F{CED}G,{,GH,FD{,E{IH,,J{,GHIJEK{F,IJK,,}KIHG,J},KJ},}KI,K}}}}
B
2
3
4
1 30 2
2020年7月19日
24
2.2单源最短路径问题算法思想
用一最小堆来存储活结点表。其优先级是结点所对应的 当前路长。
算法从图G的源顶点s和空优先队列开始。结点s被扩展 后,它的儿子结点被依次插入堆中。此后,算法从堆中 取出具有最小当前路长的结点作为当前扩展结点,并依 次检查与当前扩展结点相邻的所有顶点。如果从当前扩 展结点i到顶点j有边可达,且从源出发,途经顶点i再到 顶点j的所相应的路径的长度小于当前最优路径长度,则 将该顶点作为活结点插入到活结点优先队列中。这个结 点的扩展过程一直继续到活结点优先队列为空时为止。
[G] N, 0 =>N(25), O(0)
不搜索以不可行结点为根的子树
优先队列式分支限法:
[A] B, C => B(45), C(0)
算法设计与分析(第6章 分支限界法)

11
2014-8-27
西安邮电学院
12
2014-8-27
西安邮电学院
13
2014-8-27
西安邮电学院
14
2014-8-27
西安邮电学院
15
2014-8-27
西安邮电学院
16
2014-8-27
西安邮电学院
17
2014-8-27
西安邮电学院
18
2014-8-27
西安邮电学院Leabharlann 192014-8-27
两种方法的搜索方式比较:
回溯法:深度优先
分支限界法:广度优先或最小费用优先
2014-8-27
西安邮电学院
2
分支限界法的搜索策略:
在扩展节点处,先生成其所有的儿子节点(分支的过 程),在从当前的活节点表中选择下一个扩展节点。为了有 效选择下一个扩展节点,以加速搜索进程,在每一个活节点 处,计算一个函数值(限界的过程),并根据这些已计算出 的函数值,从当前活节点表中选择一个最有利的活节点作为 扩展节点,使得搜索向解空间树上有最优解的分支进行,以 尽快找出一个最优解。
第六章 分支限界法 Branch and Bound
2014-8-27
西安邮电学院
1
分支限界法也是一种在问题解空间上进行尝试搜索算法。 它类似于回溯法,但分支限界法和回溯法的求解目标不同。 回溯法的求解目标是找出满足约束条件的所有解,而分支限 界法的求解目标则是找出满足约束条件的一个解,或者是在 满足约束条件的解中找出使得某一目标函数值达到某种意义 下的最优解。
优先队列: (1)最大优先队列:数值大则优先级高 实现方式:最大堆 (2)最小优先队列:数值小则优先级高 实现方式:最小堆
第六章 分支与界限

• 在整个搜索过程中,每遇到一个活结点,就对它的各个孩 子结点进行目标函数可能取得值得估算,然后把以此来更 新表结点:丢弃不再需要的结点,加入新的结点。再从表 中选取“界”取极值的结点,并重复上述过程。 • 随着过程的不断深入,结点表中所估算的目标函数的极值, 越来越接近问题的解。当搜索到一个叶子结点时,如果对 该结点所估算的目标函数的值就是结点表中最大或最小值, 那么沿叶子结点到根结点的路径确定的解就是问题的解。
∞ 5 20 10 23
25 ∞ 16 51 9
41 18 ∞ 25 7
32 31 7 ∞ 11
28 26 1 6 ∞
13
14
6.2.1 费用矩阵的行归约(列归约)
• 费用矩阵c的第i行(或第j列)中的每个元素减去一个正常 数lhi(或chj),得到一个新的费用矩阵,使得新矩阵中第i 行(或第j列)中的最小值为0,称为费用矩阵的行归约 (列归约),称lhi为行归约常数,称chj为列归约常数。 0 0 1 2 3 4 1 2 3 4 0
∞ 13 3 43 4 0
0 2
3 lh0=3 4
13 ∞ 19 0
0 2 ∞ 0
0 0 0 ∞
∞ 0 19 4 16
0 ∞ 15 45 2
16 13 ∞ 19 0
3 22 2 ∞ 0
3 21 0 0 ∞
的选择中,必然包含第i行 的最小元素和第j列的最小 元素(除cij之外的)。
ch1=2
25 26
0 ∞ 15 45 2
16 13 ∞ 19 0
3 22 2 ∞ 0
3 21 0 0 ∞
h lhi ch j
j 0
3 4
∞ 5 20 10 23
第6章 分支限界法

6.3 装载问题
1. 问题描述
• 有一批共个集装箱要装上 2 艘载重量分别为 C1 和C2的轮船,其中集装箱i的重量为wi,且
w
i 1
n
i
c1 c2
• 装载问题要求确定是否有一个合理的装载方案 可将这个集装箱装上这2艘轮船。如果有,找出 一种装载方案。 • 如果一个给定装载问题有解,则采用装载策略
最短路径问题关键部分算法
while (true){ // 搜索问题的解空间 for (int j=1;j<=n;j++) if(c[E.i][j] <max && E.length+cE.i][j] < dist[j]) { // 顶点i到顶点j可达,且满足控制约束 dist[j]=E.length+c[E.i][j]; //修正数值
bestx[j] = (bestE.LChild) ? 1 : 0; bestE = bestE.parent; }
学习要点
理解分支限界法的剪枝搜索策略 掌握分支限界法的算法框架,会描述队列变化
(1)队列式(FIFO)分支限界法
(2)优先队列式分支限界法 :会确定优先级
通过应用范例学习分支限界法的设计策略
掌握两类例子每类2个例子:子集树、排列树
分支限界法与回溯法
(1)求解目标:基本相同 回溯法:通过回溯找出满足约束条件的所有解或最 优解 分支限界法:找出满足约束条件的一个解,或是在 满足约束条件的解中找出在某种意义下的最优解 (2)搜索方式:不同
3. 约束条件 1)显式约束:对分量xi的取值限定。
2)隐式约束:为满足问题的解而对不同分量之 间施加的约束。 4. 解空间:对于问题的一个实例,解向量满足显式 约束条件的所有多元组,构成了该实例的一个解空间。
第6章 分支限界法

16
算法从图G的源顶点s和空优先队列开始。 算法从图G的源顶点s和空优先队列开始。 结点s被扩展后,它的儿子结点被依次插入堆中。 结点s被扩展后,它的儿子结点被依次插入堆中。 此后, 此后,算法从堆中取出具有最小当前路长的结点 作为当前扩展结点, 作为当前扩展结点,并依次检查与当前扩展结点 相邻的所有顶点。 相邻的所有顶点。 如果从当前扩展结点i到顶点j有边可达, 如果从当前扩展结点i到顶点j有边可达,且从源 出发,途经顶点i再到顶点j 出发,途经顶点i再到顶点j的所相应的路径的长 度小于当前最优路径长度, 度小于当前最优路径长度,则将该顶点作为活结 点插入到活结点优先队列中。 点插入到活结点优先队列中。 这个结点的扩展过程一直继续到活结点优先队列 为空时为止。 为空时为止。
r=14, p=45 不可解 r=14, r=15, p=45 p=25 r=30, p=0
不可解
r=14, p=45
r=0, p=50
7
用队列式分支限界法解此问题时,用一个队列 用队列式分支限界法解此问题时,用一个队列 来存储活结点表。 来存储活结点表。
不可解
队头 B C E F
不可解 G K L M N O
第6章 分支界限法
学习要点
• 理解分支限界法的剪枝搜索策略。 理解分支限界法的剪枝搜索策略。 • 掌握分支限界法的算法框架 (1)队列式(FIFO)分支限界法 队列式(FIFO)分支限界法 (2)优先队列式分支限界法 • 通过应用范例学习分支限界法的设计策略。 通过应用范例学习分支限界法的设计策略。
11
第六部分 分支限界法

单源最短路经
• 有向图G中,每一边都有一个非负边权。求 图G的从源顶点s到目标顶点t之间的最短路 径。
2
9
12
14>8 9>8
5>3
12>4
10>7
0
3
4
7
8>7
8
4
5
6>5
6
• 剪枝:结点间的控制关系。从s出发,经过两条不同路径 到达同一顶点,这两条路径相应于解空间树的2个不同的 结点A和B,如果结点A所相应的路长小于结点B所相应的路 长,则可以将结点B为根的子树剪去,称结点A控制了结点 B。 • 优先队列中结点的优先级:结点所对应的当前路长。
• 在使用分支限界法解具体问题时,可以采 用下面两种典型方式实现活结点表
– 队列式分支限界(先进先出) – 优先队列式分支限界
1 1
2
3
4
2
3
4
队列式: 活结点表L=(2,3,4)
优先队列式: 活结点表L=(2,3,4按限界函数值确定 优先级),即哪个分支能够花最小 代价 E.length c[E.i][j] dist[j]是否更新?
j
i
j
最大团问题
• 给定一个无向图G=(V,E)。如果U包含于V,且对任 意u,v属于U有(u,v)属于E,则称U是G的一个完全子 图。G的完全子图U是G的一个团当且仅当U不包含 在G的更大的完全子图中。G的最大团是指G中所 含顶点数最多的团。
• (当前扩展结点)顶点数上界=已确定的顶点数+未确定的顶点 数的上界
六章分支限界法

6.1 分支限界法的基本思想
分支限界法与回溯法
• 回溯与分支限后评估这个部分
解: – 如果加上剩下的分量也不可能求得一个解,就不再生
首先把物品按照P(i)/W(i)≥P(i+1)/W(i+1)的衡量标准排序, 以此顺序读入物品。并且定义一个大小为物品多少的解向量X, X的一个分量就代表某个物品的装入情况。
6.2 0-1背包问题 (0-1 Knapsack Problem)
[问题描述] 设有n个物体和一个背包,物体i的重量为wi , 价值为pi ,背包的载荷为M,找一个装载方案,使得能放入 背包的物体总价值最高。
6.1 分支限界法的基本思想
(用于求解最优化问题)
目标函数限界U: 初始U可取,若x*是任一答案结点,且 c(x*)<U, 则更新U=c(x*), x*为已知答案结点值最小者。当搜索 到结点x,而c(x)>U时, x将不必扩展(剪枝)。
活动结点表: 通常采用优先队列方式组织, c(x)小者优先。
6.1 分支限界法的基本思想
E-结点一直保持到死为止的状态生成方法导致分枝-限 界方法(branch-and-bound)。
6.1 分支限界法的基本思想
分支限界法常以广度优先或以最小耗费(最大效 益)优先的方式搜索问题的解空间树。对已处理的 各结点根据限界函数估算目标函数的可能取值,从 中选取使目标函数取得极值(极大/极小)的结点 优先进行广度优先搜索不断调整搜索方向,尽快 找到解。
• 然而,如果评价函数选择得好,采用分支限界法可 能有一个小得多的常数因子。
• 好的评价函数应该有一个尽可能高的下界估计和一 个尽可能低的上界估计,从而使得搜索空间能够得 到有效的压缩,从而提高效率。
分支限界法求单源最短路径

分支限界法求单源最短路径分支限界法是一种求解最优化问题的算法,在图论中,可以用来求解单源最短路径。
本文将介绍分支限界法的基本原理和步骤,并通过一个具体的示例来说明其应用。
一、分支限界法简介分支限界法是一种穷举搜索算法,通过不断地将问题空间划分成更小的子问题,以寻找最优解。
它与传统的深度优先搜索算法相似,但在搜索过程中,通过引入上界(界限)来限制搜索范围,从而有效地剪枝和加速搜索过程。
分支限界法求解单源最短路径问题的基本思想是,首先将源点标记为已访问,然后以源点为根节点构建一棵搜索树,树中的每个节点表示当前访问的顶点,并记录到达该顶点的路径和权值。
通过遍历搜索树,逐步更新最短路径以及当前最优权值,从而找到最短路径。
二、分支限界法的步骤1. 创建搜索树:- 将源点标记为已访问,并将其作为根节点。
- 根据源点与其他顶点之间的边权值构建搜索树的第一层。
- 初始化当前最优路径和权值。
2. 遍历搜索树:- 从当前层中选择一个未访问的顶点作为扩展节点。
- 计算到达该扩展节点的路径和权值,并更新当前最优路径和权值。
- 根据已有的路径和权值,计算该扩展节点的上界,并与当前最优权值进行比较。
若上界小于当前最优权值,则进行剪枝操作,否则继续搜索。
- 将该扩展节点的子节点添加到搜索树中。
3. 更新最短路径:- 当搜索树的所有叶子节点都已遍历时,找到最短路径以及相应的权值。
三、示例分析为了更好地理解分支限界法的运行过程,我们将通过一个具体的示例来进行分析。
假设有一个有向带权图,其中包含5个顶点和6条边。
首先,我们需要构建初始搜索树,将源点A作为根节点。
根据源点与其他顶点之间的边权值,我们可以得到搜索树的第一层B(2)、C(3)、D(4)、E(5)。
接下来,我们从第一层选择一个未访问的顶点作为扩展节点。
假设选择节点B进行扩展。
此时,我们计算到达节点B的路径和权值,并更新当前最优路径和权值。
对于节点B,到达它的路径为AB,权值为2。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.3 装载问题
3. 算法的改进
// 检查右儿子结点 // 检查左儿子结点 Type wt = Ew + w[i]; if (wt <= c) { // 可行结点 右儿子剪枝
if (Ew + r > bestw && i < n) Q.Add(Ew); // 可能含最优解 Q.Delete(Ew);// 取下一扩展结点 提前更新 bestw
5. 优先队列式分支限界法
解装载问题的优先队列式分支限界法用最大优先队列存 储活结点表。 活结点x在优先队列中的优先级定义为从根结点到结点x的 路径所相应的载重量再加上剩余集装箱的重量之和。 优先队列中优先级最大的活结点成为下一个扩展结点。 在优先队列式分支限界法中,一旦有一个叶结点成为当 前扩展结点,则可以断言该叶结点所相应的解即为最优解。 此时可终止算法。
while6.3 (true)装载问题 { // 检查左儿子结点 2. 队列式分支限界法 if (Ew + w[i] <= c) // x[i] = 1 EnQueue(Q, Ew + w[i], bestw, i, n); // 右儿子结点总是可行的 EnQueue(Q, Ew, bestw, i, n); // x[i] = 0 Q.Delete(Ew); // 取下一扩展结点 if (Ew == -1) { // 同层结点尾部 if (Q.IsEmpty()) return bestw; Q.Add(-1); // 同层结点尾部标志 Q.Delete(Ew); // 取下一扩展结点 i++; // 进入下一层 } }
if (wt > bestw) bestw = wt; // 加入活结点队列 if (i < n) Q.Add(wt); }
6
6.3 装载问题
4. 构造最优解
为了在算法结束后能方便地构造出与最优值相应的最 优解,算法必须存储相应子集树中从活结点到根结点的路 径。为此目的,可在每个结点处设置指向其父结点的指 针,并设置左、右儿子标志。 class QNode { QNode *parent; // 指向父结点的指针 bool LChild; Type weight; } // 左儿子标志 // 结点所相应的载重量
4
6.3 装载问题
3. 算法的改进
节点的左子树表示将此集装箱装上船,右子树表示不将 此集装箱装上船。 设bestw是当前最优解;Ew是当前扩展结点所相应的重 量;r是剩余集装箱的重量。 则当Ew+rbestw时,可将其右子树剪去。 另外,为了确保右子树成功剪枝,应该在算法每一次进 入左子树的时候更新bestw的值。
a
b
在布线时,电路只能沿直线 或直角布线,为了避免线路 相交,已经布线了的方格要 做封锁标记,其它线路不允 许穿过被封锁了的方格。
11
6.4 布线问题
2. 算法思想
1)解此问题的队列式分支限界法从起始位置a开始将它作 为第一个扩展结点。与该扩展结点相邻并且可达的方格成 为可行结点被加入到活结点队列中,并且将这些方格标记 为1,即从起始方格a到这些方格的距离为1。 2)接着,算法从活结点队列中取出队首结点作为下一个扩 展结点,并将与当前扩展结点相邻且未标记过的方格标记 为2,并存入活结点队列。 3)这个过程一直继续到算法搜索到目标方格b或活结点队 列为空(表示没有通路)时为止。
7
6.3 装载问题
4. 构造最优解
找到最优值后,可以根据parent回溯到根节点,找到 最优解。 // 构造当前最优解 for (int j = n - 1; j > 0; j--) { bestx[j] = bestE->LChild; bestE = bestE->parent; }
8
6.3 装载问题
2. 队列式分支限界法
1)如何获知当前结点是叶子?即如何判断当前结 点的层数? 解决:设置同层尾部标志,每处理到同层尾部,层 数i++;或者将层数归入结点类的成员中去。 2)如何获得从根到当前可行叶节点的一条从上至 下的纵向路径? 解决:将父节点的指针和左右标志归入结点类成员 中去,以便找到最优叶节点时,从叶向根回溯得到 路径。 3
9
6.3 装载问题
5. 优先队列式分支限界法 具体实现优先队列的时候,有两个实现 难
点需要处理:
1)优先队列中节点的 “ 优先级 ” 如何定义? 是否要搜索完所有叶节点?或者是第1个可 行的叶节点即为最优解? 2)如何保存从根到当前扩展节点的路径?
10
6.4 布线问题
1. 问题描述
印刷电路板将布线区域划分成n×n的方格阵列,如下 图所示。精确的布线问题要求确定连接方格a的中点到方格 b的中点的最短布线方案。
6.3 装载问题
1. 问题描述
有一批共个集装箱要装上2艘载重量分别为C1和C2的轮 船,其中集装箱i的重量为Wi,且
n
w c c
i 1 i 1
2
装载问题要求确定是否有一个合理的装载方案可将这个集 装箱装上这2艘轮船。如果有,找出一种装载方案。 容易证明:如果一个给定装载问题有解,则采用下面的策 略可得到最优装载方案。 (1)首先将第一艘轮船尽可能装满; (2)将剩余的集装箱装上第二艘轮船。
找到目标位置后,可以通过回溯方 法找到这条最短路径。 15
6.4 布线问题
3. 算法实现
找到目标位置后,可以通过回溯方法找到这条最短路径。 here=finish; PathLen= grid[here.row][here.col] - 2; for (int j = PathLen-1; j>=0; j--) { //往四个邻域位置寻找前驱位置; …… //here=前驱位置; …… } //记录下here走过的路径就是从起点到终点的最短布线路径
16
6.5 0-1背包问题
P206-210 算法
“完全二叉树”为搜索空间树。 采用“优先队列”为活结点表,优先级为该结点上 界函数Bound计算得出,同回溯算法章节讨论的 Bound值。 最大值堆来实现“优先队列”。 左儿子可行,则入优先队列;右儿子一定可行, 但不一定入优先队列,只有满足上界约束才入优先 队列中。 看P209 MaxKnapsack()。
设置边界的围墙 for (int i = 0; i <= m+1; i++) grid[0][i] = grid[n+1][i] = 1; // 顶部和底部 for (int i = 0; i <= n+1; i++) grid[i][0] = grid[i][m+1] = 1; // 左翼和右翼
14
17
6.7 旅行售货员问题
P213-216 算法
“排列树”为搜索空间树。 用一个“优先队列”存储活结点表。 看P214 BBTSP()。
18
12
6.4 布线问题
2. 算法思想
3 2 2 1 1 a 2 1 2
1 2 3
a b
4 5 6 6 7 8 7 8 8 1 2
b
3 4 5 6 8 7
13
6.4 布线问题
3. 算法实现
定义移动方向 的相对位移
Position offset[4]; offset[0].row = 0; offset[0].col = 1; // 右 offset[1].row = 1; offset[1].col = 0; // 下 offset[2].row = 0; offset[2].col = -1; // 左 offset[3].row = -1; offset[3].col = 0; // 上
1
6.3 装载问题
2. 队列式分支限界法 具体实现的时候,总是将当前扩展结点的所 有儿子入队,然后从队首取结点作为下一个 扩展结点,这有两个实现难点需要处理: 1)如何获知当前结点是叶子?即如何判断 当前结点的层数? 2)如何获得从根到当前可行叶节点的一条 从上至下的纵向路径?
2
6.3 装载问题
6.4 布线问题
3. 算法实现
for (int i = 0; i < NumOfNbrs; i++) { nbr.row = here.row + offset[i].row; nbr.col = here.col + offset[i].col; if (grid[nbr.row][nbr.col] == 0) { // 该方格未标记 grid[nbr.row][nbr.col]=grid[here.row][here.col] + 1; if ((nbr.row == finish.row) && (nbr.col == finish.col)) break; // 完成布线 Q.Add(nbr); } }