问题描述

印刷电路板将布线区域划分成nxm个方格阵列,如图1所示。精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案。在布线时,电路只能沿直线或直角布线, 如图2所示。为了避免线路相交,已布了线的方格做了封锁标记,其他线路不允许穿过被封锁的方格。

题目分析

这个问题很类似迷宫问题,因此我们可以使用回溯法来解决,这里稍微提一下,如果使用回溯法,那么解空间将是一颗子集树。
但是这里我们还是决定使用分支限界法,因为回溯法是深度优先,它会一条路走到黑,然后计算出一条路径,然后回到起点,换一条路走到黑,再计算出一条路径,看是否更短…需要不停地走到进头再回溯,然后再次走到尽头。
但是分支限界法,是一种广度优先,它会每次寻找一层,不需要只选择一条路一直走。这样每一层的所有结点都会被加入队列。我们一层一层地寻找,先遇到目标点的就是最短路径,也不需要回溯了。因为大家从同一起点出发,哪一条先到了说明哪一条最短。这也确实是分支限界法的思想——使用队列或者优先队列。
剩下的就是这个题目的细节处理了。我们怎么表示某个格子已经有围墙了,哪个格子没有呢?又如何去标志目前的路径长度呢?
我们知道,分支限界法是广度优先搜索,所以每一层的路径长度都是相等的,区别在于某一条路径在同一层可能已经到了目标点。明确了这一点我们就知道了,处于遍历过程中同一层的所有格子都具有相同的路径长度,所以我们可以将其一起记录下来,直接填在我们的nm表格中即可.
于是我们声明一个n
m的二维矩阵grid,用1表示这里有围墙,不能填入,用0表示可以填入。于是根据迷宫问题的思路,我们预处理的时候将表格的四条边全部填为1,因为四条边上的点是不会到达目标点的,而且它们都是尽头的点,不需要再去访问填充了。将起始点的邻居从2开始标记,下一层是3,再下一层是4…依次类推,最终到终点的填充数-2即可得到最短路径长度。

由于我们只能走直角或者直线,所以我们只看上下左右四个方向即可。所以只需要给出一个增量数组,表示这四个方向。
剩下的细节,比如创立一个结构体position来表示每个方格的位置,属性为row和col。初始时,判断start和finish是否相等,如果相等可以直接返回,表示我们已经找到了最终的位置。
等我们计算出了最终的最短路径,我们可以通过向前回溯的方法,找到最短路径的中间方格。将结束位置当作当前位置,用j表示当前路径长度,0<=j<=路径长度-1仍然用之前的增量数组寻找邻居格子nbr,如果发现邻居格子填充的值为j+2,则可以退出当前邻居的查找,将其记录进path数组,准备找寻第二个邻居…依次类推,直到j=0.我们就找到了最终的具体路径和最短路径长度。

代码

#include <iostream>
#include <queue>
using namespace std;
//定义一个表示电路板上方格位置的结构体
struct Position
{int row;int col;
};
//计算从起始位置start到目标位置finish的最短布线路径
//start为起始位置,finish为目标位置,PathLen为路径长度,path为一个数组,表示经过的路径
//n为行数,m为列数
bool FindPath(Position start,Position finish,int& PathLen,Position* &path,int m,int n)
{int grid[n+1][m+1];//如果初始位置和目标位置重合,就直接返回if((start.row==finish.row) && (start.col==finish.col)){PathLen = 0;return true;}//对四个边缘进行建立围墙,方格值为1表示不允许布线,标志为0可以布线for(int i = 0;i <= m+1;i++)grid[0][i] = grid[n+1][i] = 1;for(int j = 0;j <= n+1;j++)grid[j][0] = grid[j][m+1] = 1;Position offset[4];//设置4个偏移量,我们要向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 numofnbrs = 4;//邻居的数目Position here,nbr;//表示此时所在的方格位置以及它的邻居here.row = start.row;here.col = start.col;grid[start.row][start.col] = 2;//初始化位置定为2queue<Position>Q;//建立方格队列,邻居存入int flag = 0;//标志位do{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)){flag = 1;break;//布线完成}Q.push(nbr);}}if(flag)break;//布线完成//活结点队列是否非空if(Q.empty())return false; Q.pop();//将上一扩展结点删除here = Q.front();//取下一个扩展结点  } while (true);//构造最短布线路径PathLen = grid[finish.row][finish.col] - 2;//定义路径path = new Position[PathLen];//回溯遍历找到路径here = finish;for(int j = PathLen - 1;j >= 0;j++){path[j] = here;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] == j + 2)break;//找到了路径上的前一个点}here = nbr;}return true;
}

总结

分支界限问题我个人有一种不太正确但是比较有效的理解方法,分支限界法=回溯+贪心(这其实是错误的,因为回溯是dfs,而分支限界是bfs,但是基本思想是一样的,都是向下遍历,只不过分支遍历提前找到了最优的并加入队列)。所以我们每次见到一个可以用回溯法解决的问题,都要思考一下用分支限界法能不能解决,因为通常分支限界更容易(记得使用队列或者优先队列)。
同样遇到分支界限问题也要思考一下是否可以使用回溯法解决,比如这道题其实我们用回溯法也可以,稍微复杂一些,但只是dfs的过程。记住最重要的几步——穷举选择种类,做选择,向下递归,撤销选择回溯。也可以快速解决这个问题,关于回溯的解决方法下次通过博客记录下来。

分支限界法之布线问题相关推荐

  1. 最速下降法极小化rosenbrock函数 代码_典型算法思想与应用9|分支限界法与电路布线问题

    分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树. (1) 在分支限界法中,每一个活结点只有一次机会成为扩展结点.活结点一旦成为扩展结点,就一次性产生其所有儿子结点. (2) ...

  2. 分支界限法0 1背包 c语言,分支限界法之布线问题(1)

    一.要求: 1.输入电路板区域n*m以及布线的起始位置和结束位置: 2.输出布线方案: 3.可以使用c或者vc实现 二.问题分析及实验原理: 在n*m的方格阵列中存在封锁区域(布线时必须绕开的区域), ...

  3. 布线问题 分支限界法

    [分支限界法]布线问题 印刷电路板将布线区域划分成n×m个方格如图a所示.精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案.在布线时,电路只能沿直线或直角布线,如图b所示.为了避 ...

  4. 算法设计之五大常用算法设计方法总结

    算法设计之五大常用算法设计方法总结 一.[分治法] 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再 ...

  5. 2017年下半年软件设计师选择题

    ''' 2019.5.10 ''' (1) 八进制表示方法由数字0开头,十六进制由数字0加小写字母x开头 (2) 存储 只读存储器(ROM)存储的内容是固定不变的,只能读出而不能写入的半导体存储器 读 ...

  6. 布线问题分支限界法java_大型布线:Java云应用程序缺少的技术

    布线问题分支限界法java 您是否曾经想过,为什么大多数Java框架中的依赖项注入仅用于本地进程内服务而不是分布式服务? 我最近在2013年EMC世界大会上遇到了Paul Maritz的主题演讲 (跳 ...

  7. 电路布线问题(分支限界法)

    一.问题描述 印刷电路板将布线区域划分成n*m个方格阵列. 精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线方案. 在布线时,电路只能沿直线或直角布线. 为了避免线路相交,已布了线的 ...

  8. 分支限界法求解电路布线问题

    分支限界法求解电路布线问题 #include <iostream> #include <queue> #include <stack> using namespac ...

  9. 布线问题-分支限界法

    2019独角兽企业重金招聘Python工程师标准>>> 问题描述: 印刷电路板不限区域划分成n*m个方格阵列.如下图所示 精确的电路布线问题要求确定连接方格a的中点,到连接方格b的中 ...

  10. 算法笔记之分支限界法

    广度优先 广度优先搜索,其实就是层次遍历,程序采用队列来实现. 算法思想 从根开始,常以BF或以最小耗费(即最大收益)优先的方式搜索问题的解空间树.首先将根结点加入活结点表,接着从活结点表中取出根结点 ...

最新文章

  1. unordered_map的使用特性
  2. Kotlin极简教程:第4章 基本数据类型与类型系统
  3. DHCP的基本介绍以及在HC3上配置DHCP中继和DHCP snooping
  4. 信息系统项目管理师:第5章:项目范围管理- 章节真题+解析
  5. 笔记-项目立项管理-项目的可行性研究-可行性研究内容
  6. 入坑-DM导论-第一章绪论笔记
  7. 移动计算机怎么开机密码,win7忘记开机密码解决办法
  8. socket api中send()和recv()函数工作原理与要点
  9. Linux环境无文件渗透执行ELF:memfd_create、ptrace
  10. if语句中的赋值与判断
  11. python向上取整_python向上取整-取整,向上
  12. PLC系统的选型技巧
  13. UCOS操作系统——任务管理(二)
  14. Matlab中MOSEK优化包的配置及使用
  15. 多测师_设置 Linux 支持中文
  16. vmware虚拟机的基础使用
  17. 语音信号处理-python
  18. 怎么用c语言测试音频文件,如果用c语言程序读取一段音频文件要如何做,具体要调用哪些函数,在网上搜索了半天,乱七八糟的,找不到什么有用的信息...
  19. 邮件工具-MailUtil(发送邮件)
  20. WIN10版本安装JDK

热门文章

  1. 软件测试必读的经典书籍
  2. Dynamsoft SourceAnywhere for VSS 5.4安装配置指南
  3. FusionChartsFree用法简介
  4. python 读取地震道头数据_通过计算机编程快速读取地震数据的方法
  5. HandlerSocket的安装实例及性能测试
  6. java socket 局域网_javase基础socket编程之局域网聊天,局域网文件共享
  7. 浅析openvn redirect-gateway组建公司专网的使用
  8. nod32防火墙配置与系统防黑手册
  9. 中标麒麟系统安装步骤
  10. 6月读书《有效的管理者》笔记