0035算法笔记——【分支限界法】布线问题
分支限界法解题算法框架

分支限界法解题算法框架分支限界法是一种建模和求解复杂优化问题的有效算法,它源于笛卡尔的科学思想,被认为是能够解决复杂优化问题的革命性工具。
它的基本思想是:分支限界法以树状结构的方式求解优化问题,不断的分割搜索空间,找到最优解。
1、分支限界法的基本概念分支限界法是求解优化问题的一种方法,它将解空间划分为若干个子空间,在每个子空间中评估优化指标,根据分支限界准则,搜索最优解。
它主要分为以下几个步骤:(1)定义一个有限的决策空间,并设置目标函数的优化指标;(2)将决策空间划分为若干个子空间,并设置有效限界和分裂标准;(3)在每个子空间中进行搜索,并进行评价;(4)根据评价结果,重复(2)、(3)步骤,直至满足停止条件,搜索得到最优解。
2、分支限界法的优势分支限界法是一种求解优化问题的有效算法,它在优化技术中占有很重要的地位。
其优势在于:(1)分支限界法可以使用更少的计算量,求解复杂的优化问题;(2)分支限界法采用分支和分割的方式,可以更好的避免搜索局部最优,获得更可靠的最优解;(3)分支限界法可以认为是一种智能化、自适应的搜索技术,它可以有效提高计算效率;(4)分支限界法易于理解,实现比较容易,可以节省程序员的工作量和计算时间。
3、案例应用分支限界法在很多领域有广泛的应用,其中最常见的应用是解决资源分配问题。
可以将需要分配的资源划分为若干个变量,然后使用分支限界法寻找该资源分配问题的最优解。
在运输问题中,如果要在有限的时间内最大限度地利用车辆从一个汽车站点出发,向其他若干个目的地发送货物,可以使用分支限界法来求解,以便在有限的时间内找到最优解。
在装配线调度问题中,如果要解决多个工序同时进行的装配线调度问题,则可以使用分支限界法来求解。
4、总结分支限界法解题算法是一种求解优化问题的有效算法,它将求解空间划分为若干个子空间,采用分支和分割的方式,找到最优解。
该算法具有计算量小、避免搜索局部最优、易于实现等优点,可以用于解决复杂优化问题,在资源分配、运输、装配线调度等领域都有广泛的应用。
算法分析与设计分支限界法

算法分析与设计分支限界法分支限界法是一种常用的优化算法,它通过剪枝和分支的方式在空间中找到最优解。
在算法设计与分析中,分支限界法在求解组合优化问题和图论问题中有广泛应用。
分支限界法的基本思想是将问题划分为一个个子问题,并对每个子问题进行求解,同时通过剪枝操作减少空间。
算法从一个初始状态开始,通过扩展子节点来生成树。
在每个节点上,先判断该节点是否需要剪枝操作。
如果需要剪枝,则舍弃该节点及其子节点;如果不需要剪枝,则继续扩展该节点为新的可能解。
通过不断扩展和剪枝操作,最终找到最优解。
分支限界法的核心是选择一个合适的策略来确定节点的扩展顺序。
常用的策略包括优先级队列、最小堆、最大堆等。
这些策略可以根据问题的性质和特点来选择,以保证效率。
同时,剪枝操作也是分支限界法中关键的一环。
剪枝操作有多种方式,如上界和下界剪枝、可行剪枝、标杆剪枝等。
通过剪枝操作,可以减少空间,提高算法的效率。
分支限界法的时间复杂度通常是指数级别的,因为每个节点需要根据策略进行扩展,并进行剪枝操作。
然而,通过合理选择策略和剪枝操作,可以显著减少空间,降低时间复杂度。
此外,分支限界法还可以通过并行计算等技术进一步提高效率。
分支限界法在求解组合优化问题中有广泛应用。
组合优化问题是在有限的资源条件下,通过组合和选择来达到最优解的问题。
例如,旅行商问题、背包问题等都是经典的组合优化问题,而分支限界法可以在有限的时间内找到最优解。
在图论问题中,分支限界法也有重要的应用。
例如,最短路径问题、图着色问题等都可以通过分支限界法求解。
总之,分支限界法是一种基于和剪枝的优化算法,通过合理选择策略和剪枝操作,在有限的时间内找到最优解。
该算法在组合优化问题和图论问题中有广泛应用,可以有效提高问题求解的效率。
在实际应用中,可以根据问题性质和特点选择合适的策略和剪枝操作,以达到最佳的求解效果。
算法设计与分析 分支限界

…
13
纲要
一、分支限界的基本思想
二、背包问题
三、P和NP
14
问题定义
0-1背包问题
给定n个物品,商品i有两个属性i 和i ,分别代表重量和价格,
背包所承受的物品重量为W
0-1背包问题的目的是要选择一个物品的子集,使其总重量≤W,而价值最大。
解空间
假设解可以有向量( , ,…, )表示, ∈{0,1}, =1表示物品i被放进
(成为死节点),把剩下来的节点加到活节点的表中,然后,从这个
表中选一个节点作为下一个扩展节点。
7
分支限界法
从活节点的表中选一个节点并扩展它。这个扩展操作持续到找到解或这
个表为空为止。
选择下一个扩展节点的方法∶
1)先进先出(FIFO)
这个方法是按节点放进表中的次序从活节点表中选择节点。这个活节点
表可被看作一个队列。使用广度优先来搜索这个棵树。
在这个节点上我们得到的下界大于或等于上界,那么就没有必要在扩
展这个节点既不需在延伸这个分支。
·对于最大化问题规则正好相反:一旦上界小于或等于先前确定的下界,
那么就剪掉这个枝。
4
分支限界法
·首先,分支限界是对最优化问题可行解进行剪枝的一个方法。
·将搜索集中在有希望得到解的分支上。也就是说,在基于上下界和可
时,活节点表可用一个最大堆来表示。下一个扩展节点为最大收益的节点。
9
解空间树
扩展节点
死节点
活节点
success
10
分支限界法
使用分支限界法至少需要注意以下几点:
1.怎么样计算上界,极大值问题;
算法分析及设计分支限界法

a 21
b 32
c 43
• 将结点8作为扩展结点0-1-5-8-12-10
路径长度小于0-2-6-9-10,选择路径02-6-9-10
u
ed
g
f
h
作为最短路径。 • 从s到T的最短路为0-2-6-9-10,长度
Hale Waihona Puke 524 5 9 4 5 6 12 5 6 6
为8。
q
km
l
5 6 78 6 9
o
r
8 10 p
2021/6/18
2
6.1
分支限界法的基本思想
2. 分支限界法基本思想 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩 展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导 致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
12 10 8 8 8 10
2021/6/18
21
第6章 分支限界法
本章主要知识点:
6.1
分支限界法的基本思想
6.2
单源最短路径问题
6.3 0-1背包问题
2021/6/18
22
6.2
单源最短路径问题
1. 问题描述
给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点, 称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权 之和。这个问题通常称为单源最短路径 问题。
2021/6/18
4
6.1
分支限界法的基本思想
• 例如:考虑n=3时0-1背包问题,其中w=[16,15,15], p=[45,25,25],c=30。
学习电脑信息五大常用算法之五:分支限界法

五大常用算法之五:分支限界法五大常用算法之五:分支限界法分支限界法一、基本描述类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。
但在一般情况下,分支限界法与回溯法的求解目标不同。
回溯法的求解目标是找出T中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
(1)分支搜索算法所谓“分支”就是采用广度优先的策略,依次搜索E-结点的所有分支,也就是所有相邻结点,抛弃不满足约束条件的结点,其余结点加入活结点表。
然后从表中选择一个结点作为下一个E-结点,继续搜索。
选择下一个E-结点的方式不同,则会有几种不同的分支搜索方式。
1)FIFO搜索2)LIFO搜索3)优先队列式搜索(2)分支限界搜索算法二、分支限界法的一般过程由于求解目标不同,导致分支限界法与回溯法在解空间树T上的搜索方式也不相同。
回溯法以深度优先的方式搜索解空间树T,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树T。
分支限界法的搜索策略是:在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展对点。
为了有效地选择下一扩展结点,以加速搜索的进程,在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
问题的解空间树是表示问题解空间的一棵有序树,常见的有子集树和排列树。
在搜索问题的解空间树时,分支限界法与回溯法对当前扩展结点所使用的扩展方式不同。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。
活结点一旦成为扩展结点,就一次性产生其所有儿子结点。
在这些儿子结点中,那些导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被子加入活结点表中。
(原创精品)分支限界法

分支限界法概述:分支定界(branch and bound) s搜索法是一种在问题的解空间树上搜索问题的解的方法。
分支定界算法采用广度优先或最小耗费优先的方法搜索解空间树,并且,在分支定界算法中,每一个活结点只有一次机会成为扩展结点。
搜索策略1 产生当前扩展结点的所有孩子结点;2 在产生的孩子结点中,抛弃那些不可能产生可行解(或最优解)的结点;3 将其余的孩子结点加入活结点表;4 从活结点表中选择下一个活结点作为新的扩展结点。
5 如此循环,直到找到问题的可行解(最优解)或活结点表为空。
从活结点表中选择下一个活结点作为新的扩展结点根据选择方式的不同分支定界算法通常可以分为两种形式:①队列式(FIFO)分支限界法队列式分支限界法将活结点表组织成一个队列,并按队列的先进先出原则选取下一个结点为当前扩展结点②优先队列式的分支限界法将活结点表组织成一个队列,并按优先队列中规定的优先级选取优先级最高的下一个节点成为当前扩展节点最大优先队列:使用最大堆,体现最大效益优先最小优先队列:使用最小堆,体现最小费用优先分支限界法和回溯法的区别①求解目标不同:回溯法的求解目标是找出解空间树中满足约束条件的所有解分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解②搜索方式不同:回溯法以深度优先的方式搜索解空间树分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树③搜索问题的解空间树方面:在分支限界法中,每一个活结点只有一次机会成为扩展结点。
活结点一旦成为扩展结点,就一次性产生其所有儿子结点。
在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。
这个过程一直持续到找到所需的解或活结点表为空时为止。
什么是剪枝(以走迷宫举例)我们在“走迷宫”的时候,一般回溯法思路是这样的:1、这个方向有路可走,我没走过2、往这个方向前进3、是死胡同,往回走,回到上一个路口4、重复第一步,直到找着出口这样的思路很好理解,编程起来也比较容易。
(完整版)分支限界算法作业分配问题

分支限界法的研究与应用摘要:分支限界法与回溯法的不同:首先,回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解。
其次,回溯法以深度优先的方式搜索解空间树,而分支限界法则一般以广度优先或以最小耗费优先的方式搜索解空间树。
再者,回溯法空间效率高;分支限界法往往更“快”。
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
在分支限界法中,每一个活结点只有一次机会成为扩展结点。
活结点一旦成为扩展结点,就一次性产生其所有儿子结点。
在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。
此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。
这个过程一直持续到找到所需的解或活结点表为空时为止。
常见的分支限界法有:队列式分支限界法,按照队列先进先出原则选取下一个结点为扩展结点。
栈式分支限界法,按照栈后进先出原则选取下一个结点为扩展结点。
优先队列式分支限界法,按照规定的结点费用最小原则选取下一个结点为扩展结点(最采用优先队列实现)。
分支搜索法是一种在问题解空间上进行搜索尝试的算法。
所谓分支是采用广度优先的策略国,依次搜索E-结点的所有分支,也就是所有的相邻结点。
和回溯法一样,在生成的结点中,抛弃那些不满足约束条件的结点,其余结点加入活结点表。
然后从表中选择一个结点作为下一个E-结点,断续搜索。
关键词:分支限界法回溯法广度优先分支搜索法目录第1章绪论 (3)1.1 分支限界法的背景知识 (3)1.2 分支限界法的前景意义 (3)第2章分支限界法的理论知识.................. 错误!未定义书签。
2.1 问题的解空间树 ............................................... 错误!未定义书签。
布线问题(分支限界法)

布线问题(分⽀限界法)⼀、⾸先说⼀下分⽀限界法的思想:(1)⽐较:分⽀限界法和回朔法有相似之处,但是回朔法是搜索问题的所有解,采⽤深度优先搜索;⽽分⽀限界法是搜索问题的最优解,采⽤的是⼴度优先搜索;(2)核⼼思想:分⽀限界法中,每⼀个活节点都只有⼀次机会成为扩展节点。
活节点⼀旦成为扩展节点,就⼀次性产⽣所有的⼉⼦节点。
在这些⼉⼦节点中,导致不可⾏解或者导致⾮最优解的⼉⼦节点被舍弃,其余⼉⼦节点被加⼊活节点表中。
此后,从活节点表中取下⼀节点成为当前扩展节点,并重复上述节点的扩展过程。
这个过程⼀直在持续到找到所需要的最优解或者活节点表为空时为⽌;其中:选择扩展节点的⽅式可以分为:队列式分⽀限界法和优先队列式分⽀限界法。
后者相对于前者的改进是对活节点加⼊了优先级,优先级最⾼的成为扩展节点(通常通过最⼤堆最⼩堆实现);⼆、布线问题描述:代码如下://队列类 : LinkedQueue.h#ifndef LINKEDQUEUE_H#define LINKEDQUEUE_Htemplate <class Type>class LinkedQueue{public:LinkedQueue(){};explicit LinkedQueue(int Capacity); //创建队列bool IsEmpty(); //判断是否空bool IsFull(); //判断是否满bool Add(Type &cell); //向队列中加⼊元素bool Delete(Type &cell); //删除队列中的元素~LinkedQueue();private:Type cell;Type *ptr; //队列中的元素指针int QueueLen; //队列元素个数int QueueCapacity; //队列容量int Head;int Tail;};template <class Type>LinkedQueue<Type>::~LinkedQueue(){delete[]ptr;ptr = nullptr;}template <class Type>LinkedQueue<Type>::LinkedQueue(int Capacity){QueueCapacity = Capacity;Head = 0;Tail = 0;QueueLen = 0;ptr = new Type[QueueCapacity];}template <class Type>bool LinkedQueue<Type>::IsEmpty(){if (QueueLen == 0)return true;elsereturn false;}template <class Type>bool LinkedQueue<Type>::IsFull(){if (QueueLen == QueueCapacity)return true;elsereturn false;}template <class Type>bool LinkedQueue<Type>::Add(Type &cell){if (IsFull())return false;else{ptr[Tail] = cell;Tail++;QueueLen++;return true;}}template <class Type>bool LinkedQueue<Type>::Delete(Type &cell){if (IsEmpty())return false;else{cell = ptr[Head];Head++;QueueLen--;return true;}}#endif//使⽤分⽀限界法解决布线问题main.cpp//====================================================#include <iostream>#include "LinkedQueue.h"//#include <queue>using namespace std;int n, m; //布线盘是n * m⼤⼩class Position{public:int row;int col;};bool FindPath(int ** grid , Position start, Position finish, int &PathLen, Position * &path) {//计算从起始位置start到⽬标位置finish的最短布线路径//找到最短布线路径则返回true,否则返回flaseif ((start.row == finish.row) && (start.col == finish.col)){PathLen = 0;return true;}//设置⽅格阵列“围墙”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; //左翼和右翼}//初始化相对位移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; //上int neigh_num = 4; //相邻⽅格数Position here, nbr;here.row = start.row;here.col = start.col;grid[start.row][start.col] = 2;//标记所有可以到达的⽅格位置LinkedQueue<Position> Q(n * m + 1); //队列//queue<Position> Q(); //队列//标记可到达的相邻⽅格do {for (int i = 0; i < neigh_num; 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); //压⼊队列称为活节点}}//是否到达⽬标位置finish?if ((nbr.row == finish.row) && (nbr.col == finish.col)) //完成布线,是否要加这⼀步? break;//活节点队列是否⾮空if (Q.IsEmpty()) //⽆解return false;Q.Delete(here); //取下⼀个扩展节点} while (true);//构造最短布线路径PathLen = grid[finish.row][finish.col] - 2;path = new Position[PathLen];//从⽬标位置finish开始向起始位置回溯here = finish;for (int j = PathLen - 1; j >= 0; j--){path[j] = here;//找前驱位置for (int i = 0; i < neigh_num; i++){nbr.row = here.row + offset[i].row;nbr.col = here.col + offset[i].col;if (grid[nbr.row][nbr.col] == j + 2)break;}here = nbr; //向前移动}return true;}int main(void){Position start, finish; //开始位置和⽬标位置int PathLen; //最短路径的长度Position *path; //记录的最短路径cout << "请输⼊布线盘的⼤⼩,n * m 规格: " << endl;cin >> n >> m;cout << "请输⼊开始位置(x , y) :" << endl;cin >> start.col >> start.row;cout << "请输⼊结束位置(x , y) :" << endl;cin >> finish.col >> finish.row;int ** grid = new int*[n + 2];for (int i = 0; i < n + 2; i++){grid[i] = new int[m + 2];}for (int i = 0; i < n + 2; i++){for (int j = 0; j < m + 2; j++){grid[i][j] = 0;}}FindPath(grid, start, finish, PathLen, path);for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){cout << grid[i][j] << " ";}cout << endl;}cout << "最短路径是: " << endl;cout << PathLen << endl;system("pause");return 0;}效果图类似:。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
问题描述印刷电路板将布线区域划分成n×m个方格如图a所示。
精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。
在布线时,电路只能沿直线或直角布线,如图b所示。
为了避免线路相交,已布了线的方格做了封锁标记,其它线路不允穿过被封锁的方格。
一个布线的例子:图中包含障碍。
起始点为a,目标点为b。
算法思想解此问题的队列式分支限界法从起始位置a开始将它作为第一个扩展结点。
与该扩展结点相邻并且可达的方格成为可行结点被加入到活结点队列中,并且将这些方格标记为1,即从起始方格a到这些方格的距离为1。
接着,算法从活结点队列中取出队首结点作为下一个扩展结点,并将与当前扩展结点相邻且未标记过的方格标记为2,并存入活结点队列。
这个过程一直继续到算法搜索到目标方格b或活结点队列为空时为止。
即加入剪枝的广度优先搜索。
算法具体代码如下:1、Queue.h[cpp]view plain copy1.#include<iostream>ing namespace std;3.4.template <class T>5.class Queue6.{7.public:8. Queue(int MaxQueueSize=50);9. ~Queue(){delete [] queue;}10.bool IsEmpty()const{return front==rear;}11.bool IsFull(){return ( ( (rear+1) %MaxSize==front )?1:0);}12. T Top() const;13. T Last() const;14. Queue<T>& Add(const T& x);15. Queue<T>& AddLeft(const T& x);16. Queue<T>& Delete(T &x);17.void Output(ostream& out)const;18.int Length(){return (rear-front);}19.private:20.int front;21.int rear;22.int MaxSize;23. T *queue;24.};25.26.template<class T>27.Queue<T>::Queue(int MaxQueueSize)28.{29. MaxSize=MaxQueueSize+1;30. queue=new T[MaxSize];31. front=rear=0;32.}33.34.template<class T >35.T Queue<T>::Top()const36.{37.if(IsEmpty())38. {39. cout<<"queue:no element,no!"<<endl;40.return 0;41. }42.else return queue[(front+1) % MaxSize];43.}44.45.template<class T>46.T Queue<T> ::Last()const47.{48.if(IsEmpty())49. {50. cout<<"queue:no element"<<endl;51.return 0;52. }53.else return queue[rear];54.}55.56.template<class T>57.Queue<T>& Queue<T>::Add(const T& x)58.{59.if(IsFull())cout<<"queue:no memory"<<endl;60.else61. {62. rear=(rear+1)% MaxSize;63. queue[rear]=x;64. }65.return *this;66.}67.68.template<class T>69.Queue<T>& Queue<T>::AddLeft(const T& x)70.{71.if(IsFull())cout<<"queue:no memory"<<endl;72.else73. {74. front=(front+MaxSize-1)% MaxSize;75. queue[(front+1)% MaxSize]=x;76. }77.return *this;78.}79.80.template<class T>81.Queue<T>& Queue<T> ::Delete(T & x)82.{83.if(IsEmpty())cout<<"queue:no element(delete)"<<endl;84.else85. {86. front=(front+1) % MaxSize;87. x=queue[front];88. }89.return *this;90.}91.92.93.template<class T>94.void Queue <T>::Output(ostream& out)const95.{96.for(int i=rear%MaxSize;i>=(front+1)%MaxSize;i--)97. out<<queue[i];98.}99.100.template<class T>101.ostream& operator << (ostream& out,const Queue<T>& x) 102.{x.Output(out);return out;}2、6d4.cpp[cpp]view plain copy1.//布线问题队列式分支限界法求解2.#include "stdafx.h"3.#include "Queue.h"4.#include <fstream>5.#include <iostream>ing namespace std;7.8.ifstream fin("6d4.txt");9.10.const int n = 7;11.const int m = 7;12.int grid[n+2][m+2];13.14.struct Position15.{16.int row;17.int col;18.};19.20.bool FindPath(Position start,Position finish,int& PathLen,Position *&path);21.22.int main()23.{24.int PathLen;25.26. Position start,finish,*path;27.28. start.row = 3;29. start.col = 2;30.31. finish.row = 4;32. finish.col = 6;33.34. cout<<"布线起点"<<endl;35. cout<<start.col<<" "<<start.row<<endl;36. cout<<"布线结束点"<<endl;37. cout<<finish.col<<" "<<finish.row<<endl;38.39. cout<<"布线方格阵列如下(0表示允许布线,1表示不允许布线):"<<endl;40.for(int i=1; i<=m; i++)41. {42.for(int j=1; j<=n; j++)43. {44. fin>>grid[i][j];45. cout<<grid[i][j]<<" ";46. }47. cout<<endl;48. }49.50. FindPath(start,finish,PathLen,path);51.52. cout<<"布线长度为:"<<PathLen<<endl;53. cout<<"布线路径如下:"<<endl;54.for(int i=0; i<PathLen; i++)55. {56. cout<<path[i].col<<" "<<path[i].row<<endl;57. }58.59.return 0;60.}61.62.bool FindPath(Position start,Position finish,int& PathLen,Position *&path)63.{64.//计算从起始位置start到目标位置finish的最短布线路径65.if((start.row == finish.row) && (start.col == finish.col))66. {67. PathLen = 0;68.return true;69. }70.71.//设置方格阵列“围墙”72.for(int i=0; i<= m+1; i++)73. {74. grid[0][i]=grid[n+1][i]=1; //顶部和底部75. }76.for(int i=0; i<= n+1; i++)77. {78. grid[i][0]=grid[i][m+1]=1; //左翼和右翼79. }80.81.//初始化相对位移82. Position offset[4];83.84. offset[0].row=0;85. offset[0].col=1;//右86.87. offset[1].row=1;88. offset[1].col=0;//下89.90. offset[2].row=0;91. offset[2].col=-1;//左92.93. offset[3].row=-1;94. offset[3].col=0;//上95.96.int NumOfNbrs=4;//相邻方格数97. Position here,nbr;98. here.row=start.row;99. here.col=start.col;100.101. grid[start.row][start.col]=2;//标记可达方格位置102. Queue<Position> Q;103.104.do {//标记相邻可达方格105.for(int i=0; i<NumOfNbrs; i++)106. {107. nbr.row=here.row + offset[i].row;108. nbr.col=here.col+offset[i].col;109.110.if(grid[nbr.row][nbr.col]==0)//该方格未被标记111. {112. grid[nbr.row][nbr.col]=grid[here.row][here.col]+1; 113.if((nbr.row==finish.row) && (nbr.col==finish.col)) 114. {115.break; //完成布线116. }117. Q.Add(nbr);118. }119. }120.//是否到达目标位置finish?121.if((nbr.row==finish.row) && (nbr.col==finish.col))122. {123.break;//完成布线124. }125.126.//活结点队列是否非空?127.if(Q.IsEmpty())128. {129.return false;//无解130. }131. Q.Delete(here);//取下一个扩展结点132. }while(true);133.134.//构造最短布线路径135. PathLen=grid[finish.row][finish.col]-2;136. path=new Position[PathLen];//从目标位置finish开始向起始位置回溯137. here=finish;138.for(int j=PathLen-1; j>=0; j--)139. {140. path[j]=here;//找前驱位置141.for(int i=0; i<NumOfNbrs; i++) 142. {143. nbr.row=here.row+offset[i].row; 144. nbr.col=here.col+offset[i].col; 145.if(grid[nbr.row][nbr.col]==j+2) 146. {147.break;148. }149. }150. here=nbr;//向前移动151. }152.return true;153.}程序运行结果如图:。