布线问题-分支限界法
时间:2022-04-22
本文章向大家介绍布线问题-分支限界法,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
问题描述:
印刷电路板不限区域划分成n*m个方格阵列。如下图所示
精确的电路布线问题要求确定连接方格a的中点,到连接方格b的中点的最短布线方案。
布线时,电路只能沿直线或直角布线。为了避免线路相交,已布的线的方格做了封锁标记,其他线路不允许穿过被封锁的方格。
分支限界法的解决方案:
首先,从起始位置a开始,将它作为第一个扩展结点。与该节点相邻,并且可达的方格成为可行结点被加入到活节点队列中,并且将这些方格标记为1.
即从起始方格a到这些扩展方格距离为1.
然后,从活节点队列中取出队首结点作为下一个扩展结点,并将于当前扩展结点相邻且为未标记过的方格标记为2,并存入或节点队列。
最后,这个过程一直到算法搜索到目标方格b或活结点队列为空时截止。
实现方案:
初始定义position,私有变量row,col,显示方格 行 列。
grid[i][j]表示方格阵列的 0 : 开放, 1 :封锁。
2个方格相同,则不必计算,直接返回最小距离。
否则,设置方格围墙,初始化位移矩阵offset。
表示距离时,0,1已经使用,直接从2开始。因此所有距离最后都要减2.
算法描述
bool FindPath(Position start,Position finish,int& PathLen,Position * &path)
{
//计算从起始位置start到目标位置finish的最短路线
//找到最短布线路径返回true,否则返回false
if((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 NumOfNbs = 4;//相邻方格数
Position here,nbr;
here.row = start.row;
here.col = start.col;
grid[start.row][start.col] = 2;
//标记可达方格的位置
LinkedQueue<Position> Q;
do
{
for(int i=0;i<NumOfNbs;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))
breakp;//完成布线
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 < 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;
}
- Android打包遇到的那些坑
- 生信人写程序1. Perl语言模板及配置
- linux中压缩与解压缩命令小结
- java arrays类学习
- 如何使用带有Dropout的LSTM网络进行时间序列预测
- 生信人写程序2. Editplus添加Perl, Shell, R, markdown模板和语法高亮
- Rfam 12.0+本地使用 (最新版教程)
- 宝马汽车安全漏洞详解:古有伯乐识良驹,今有黑客擒宝马
- string.length()与-1比较为什么会出现匪夷所思的结果
- css模块化及CSS Modules使用详解
- 使用OpenCV,Python和模板匹配来播放“Waldo在哪里?”
- C++ 字符串分割
- 算法笔记之排序
- java中String类学习
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- springboot之自动配置
- golang--连接redis数据库并进行增删查改
- golang--redis连接池
- springboot配置之使用application.properties时编码问题
- mybatis动态sql之foreach补充(二)
- golang数据结构之稀疏数组
- mybatis扩展之使用PageHelper插件进行分页(是真好用)
- 动态规划--0,1背包问题(再也不怕类似背包问题了)
- springboot配置之Profile多环境支持
- LeetCode | 102.二叉树的层次遍历
- golang数据结构之队列
- 动态规划--最长上升子序列(LIS)的长度
- golang数据结构之环形队列
- golang数据结构之单链表
- golang数据结构之双链表