问题描述:在N×MN×MN×M的方格阵列中,指定一个方格为aaa,另一个方格为bbb,问题要求找出aaa到bbb的最短布线方案(即最短路径)。布线时只能沿直线或直角,不能走斜线。黑色的单元格代表不可以通过的封锁方格。

问题分析:

  • 将方格抽象为顶点,中心方格和相邻四个方向(上、下、左、右)能通过的方格用一条边连起来。这样,可以把问题的解空间定义为一个图。
  • 该问题是特殊的最短路径问题,特殊之处在于用布线走过的方格数代表布线的长度,布线时每布一个方格,布线长度累加1。
  • 只能朝上、下、左、右四个方向进行布线。


表示左、上、右、下四个方向

  • // direction[0] 向下

    • direction[0].x = 1;
    • direction[0].y = 0;
  • // direction[1] 向上
    • direction[1].x = -1;
    • direction[1].y = 0;
  • // direction[2] 向右
    • direction[2].x = 0;
    • direction[2].y = 1;
  • // direction[3] 向左
    • direction[3].x = 0;
    • direction[3].y = -1;

表示阵列的边界:用BLACK去表示

布线问题的复杂度分析:由于每个方格成为活结点进入活结点队列最多一次,因此,活结点队列最多有n*m个结点。如果扩展每个结点需要O(1)的时间,因此,算法共耗时O(nm)。构造相应的最短路距离需要O(L)的时间,其中L是最短布线路径的长度。

具体代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include <cstring>
#include <queue>
#include <stack>using namespace std;// 宏定义黑色格子的数值
#define BLACK -2
#define NUM_DIRECTION 4// 格子结构体
struct grid
{int x;int y;grid(int x = 0, int y = 0){this->x = x;this->y = y;}
};// n1 : 棋盘的行 n2 : 棋盘的列
int n1 = 0, n2 = 0;
// a : 棋盘
int **a = NULL;
// path : 记录路径的数组
int **path = NULL;
// 开始格子的横纵坐标
int start_x = 0, start_y = 0;
// 结束格子的横纵坐标
int end_x = 0, end_y = 0;
// 方向数组
grid direction[NUM_DIRECTION];// 显示棋盘
void DisPlayGrid()
{printf("---------------------------------------------------\n");printf("棋盘如下 :\n");for (int i = 1; i <= n1; i++){for (int j = 1; j <= n2; j++){if (i == start_x && j == start_y){printf("From\t");continue;}if (i == end_x && j == end_y){printf("To\t");continue;}printf("%d\t", a[i][j]);}printf("\n");}printf("---------------------------------------------------\n");
}// 显示路径数组
void DisPlayPath()
{printf("---------------------------------------------------\n");for (int i = 1; i <= n1; i++){for (int j = 1; j <= n2; j++){printf("%d\t", path[i][j]);}printf("\n");}printf("---------------------------------------------------\n");
}// 绘制路径
void DrawPath()
{printf("---------------------------------------------------\n");int x = end_x, y = end_y;// 寻找路径的时候是逆序的,这里需要进行逆序处理stack<grid> st;st.push(grid(x, y));while (path[x][y] != 0){// 对四个方向进行探测for (int i = 0; i < NUM_DIRECTION; i++){int index_x = x + direction[i].x;int index_y = y + direction[i].y;// 找到上一个可能走过来的格子if (path[index_x][index_y] == path[x][y] - 1){x = index_x;y = index_y;// 进栈st.push(grid(x, y));break;}}}printf("路径如下 :\n");// 输出路径printf("(%d,%d)", st.top().x, st.top().y);st.pop();while (st.empty() == false){printf(" -> (%d,%d)", st.top().x, st.top().y);st.pop();}printf("\n---------------------------------------------------\n");
}int main()
{// direction[0] 向下direction[0].x = 1;direction[0].y = 0;// direction[1] 向上direction[1].x = -1;direction[1].y = 0;// direction[2] 向右direction[2].x = 0;direction[2].y = 1;// direction[3] 向左direction[3].x = 0;direction[3].y = -1;printf("请输入棋盘的大小为 n1 x n2\n");scanf("%d%d", &n1, &n2);a = new int *[n1 + 2];path = new int *[n1 + 2];for (int i = 0; i < n1 + 2; i++){a[i] = new int[n2 + 2];path[i] = new int[n2 + 2];// 初始化的时候棋盘全部置零memset(a[i], 0, sizeof(int) * (n2 + 2));// 初始化的时候路径全部置为-1memset(path[i], -1, sizeof(int) * (n2 + 2));}// 对棋盘进行外面的黑色格子包裹for (int i = 0; i < n1 + 2; i++){a[i][0] = BLACK;a[i][n2 + 1] = BLACK;}for (int i = 0; i < n2 + 2; i++){a[0][i] = BLACK;a[n1 + 1][i] = BLACK;}// 黑色格子的数量int cnt = 0;printf("请输入棋盘中黑色单元格的数量 :\n");scanf("%d", &cnt);printf("请输入黑色单元格横纵坐标\n");int x = 0, y = 0;for (int i = 0; i < cnt; i++){scanf("%d%d", &x, &y);a[x][y] = BLACK;}printf("请输入开始单元格的坐标:\n");scanf("%d%d", &start_x, &start_y);if (start_x < 1 || start_x > n1 || start_y < 1 || start_y > n2){printf("输入的开始单元格横纵坐标异常\n");return -1;}path[start_x][start_y] = 0;a[start_x][start_y] = BLACK;printf("请输入目的单元的坐标:\n");scanf("%d%d", &end_x, &end_y);if (end_x < 1 || end_x > n1 || end_y < 1 || end_y > n2){printf("输入的目的单元格横纵坐标异常\n");return -2;}// 显示棋盘信息DisPlayGrid();queue<grid> q;// 标记是否能找到出口bool flag = false;// 这里采取的是广度优先搜索的方式进行的,使用队列q.push(grid(start_x, start_y));while (q.empty() == false){grid tmp = q.front();q.pop();if (tmp.x == end_x && tmp.y == end_y){printf("可以到达终点\n");flag = true;break;}// 四个方向进行探测for (int i = 0; i < NUM_DIRECTION; i++){int index_x = tmp.x + direction[i].x;int index_y = tmp.y + direction[i].y;if (a[index_x][index_y] != BLACK){q.push(grid(index_x, index_y));// 入队的直接让它变为黑色格子,避免再次访问a[index_x][index_y] = BLACK;// 路径标记从哪里走过来的path[index_x][index_y] = path[tmp.x][tmp.y] + 1;}}}if (flag){printf("%d\n", path[end_x][end_y]);DisPlayPath();DrawPath();}else{printf("无法到达终点\n");}return 0;
}/*
9 7
13
1 5
2 3
3 3
3 5
3 6
4 3
5 6
6 4
6 5
6 6
7 6
8 3
8 5
3 2
6 7
*//*
3 3
3
1 2
2 2
3 2
1 1
3 3
*/

运行结果:

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

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

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

  2. 16 导出pcb各网络的布线长度_设计PCB流程

    1. 准备--功能确定.元器件选型(主要核心元器件) 2. 元件库建立--元器件符号.元器件封装 3. 绘制原理图--根据电路功能,将元器件符号进行连接 4. 导出网络表--将元器件的连接关系,以及元 ...

  3. 分支限界法实现最优装载c++_分支限界法

    晓强Deep Learning的读书分享会,先从这里开始,从大学开始.大家好,我是晓强,计算机科学与技术专业研究生在读.我会不定时的更新我的文章,内容可能包括深度学习入门知识,具体包括CV,NLP方向 ...

  4. ad16自动布线设置规则_pcb自动布线设置_设置线间距与宽度设置_pcb布局布线技巧...

    什么是布线 布线意思是元器件间导线连接的布置,先布好线,将导线穿过有电气连接的引脚所在的孔,这样可以在焊接元件的同时,实现元件间的连接. 布线技巧 在制作单片机的实验板时,焊位数码管时1引脚,要分别用 ...

  5. java分支限界实现装载问题_分支限界法之装载问题

    装载问题(分支限界)Dlg.cpp #include "Queue.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE ...

  6. 两道关于回溯法,分支限界法的算法题

    1.最小重量机器设计问题:设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得.设 wij    是从供应商j处购得的部件 i 的重量, cij 是相应的价格.试设计一个算法,给出总价格 ...

  7. 游戏模型师生存手册丨角色布线秘诀

    我们都知道做模型就必须布线,这是不可避免的问题,关系到日后展UV,画贴图,刷权重,以及做动画.好的布线与坏的布线,在后期绑定制作动画时区别最明显.直接影响到最后的动画效果. 静态模型对布线的要求会稍微 ...

  8. 分支限界法——以单源最短路径为例,理解什么是分支限界法

    书中开篇以回溯法举例,我们经过上一章的学习知道,回溯法实质上就是将问题的解空间列为树的结构,然后以深度优先遍历来获取我们想要的答案.而分支限界法的搜索策略与其类似,我们同样将解空间化为树结构,然后以广 ...

  9. 五大常用算法——分支限界算法详解及经典例题

    一.对比回溯法 回溯法的求解目标是找出解空间中满足约束条件的所有解,想必之下,分支限界法的求解目标则是找出满足约束条件的一个解,或是满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意 ...

  10. [收藏夹整理]电子类链接

    TI杯与MSP430部分: MSP430 定时器中断使用总结_百度文库 2014年全国大学生TI杯电子设计大赛频率补偿电路(第一版)_百度文库 2014年"TI杯"模电邀请赛 - ...

最新文章

  1. Codeforces1600数学day5[找规律CodeForces - 1059C,贪心数学A - Banh-mi CodeForces - 1062C ]
  2. python库--tensorflow--RNN(循环神经网络相关)
  3. 【RecyclerView】 七、RecyclerView.ItemDecoration 条目装饰 ( getItemOffsets 边距设置 )
  4. linux clock命令,Linux中clock命令起什么作用呢?
  5. 技术解析系列 PouchContainer Goroutine Leak 检测实践
  6. kill 进程_结束进程,查看后台进程
  7. Hashtable和HashMap类的区别
  8. windbg sx命令与简单应用
  9. Edge浏览器,设定主页(默认打开页面)方法
  10. 微软最有价值专家(MVP)四连任
  11. 基于numpy科学计算库实现线性回归linear regression
  12. java获取当前上一周、上一月、上一年的时间dxl
  13. 啊哈算法——第一章第二节:冒泡排序
  14. 华为员工违规领夜宵被发现后,被罚冻薪降考评,终身不得领夜宵,HR:哪个员工上班健身,定性考勤造假...
  15. Java中类与对象编程题
  16. 软件测试工具有哪些?--最全最新的软件测试工具下载地址都在这里!错过绝对后悔!
  17. C语言中的绝对值函数
  18. requests+正则表达式爬取猫眼电影TOP100!
  19. java获取生僻字_生僻字与16进制的转换
  20. 浅谈千万级高性能高并发网站架构

热门文章

  1. hex文件转bin格式
  2. Multisim14.0软件安装+破解
  3. 网页木马攻防实战学习笔记一
  4. 电子电路基础——知识点(下篇)
  5. 网络规划设计师水平考试备考资料(2.计算机网络原理)
  6. 申请ISO14001认证组织需要准备哪些资料
  7. 因子分析python代码_用Python实现因子分析
  8. 绍兴文理学院计算机网络期末,绍兴文理学院高频电子线路期末考试题.doc
  9. 瑞昱网卡linux通用驱动下载,realtek网卡通用驱动最新版下载
  10. MathType与Office公式编辑器,谁更强?