问题描述

用二维数组表示地图,若值为 1 则表示有障碍物,若值为 0 则表示可以通行。

输入: m*n 的二维数组,布线起点坐标,布线终点坐标。

输出: 最短布线距离以及对应的布线路径。

问题分析

从起点开始布线,将起点标记为 0 ,把四周可布线的位置标记为 起点标记值 + 1 ,同时将这些点插进队列 Q (插到队尾)。

从 Q 中取出一个点(队首元素)重复布线动作,将可布线位置标记为 取出点标记值 + 1 ,并插进 Q 。不断重复上一个动作,直到找到终点,此时终点的标记值即最短布线距离。

为什么终点的标记值会等于最短布线距离呢?

事实上对于每一点这个结论都是成立的(某点的标记值=该点到起点的最短距离)。

(方块表示起点,椭圆表示终点)

在布线的过程中,始终遵循的规则是:标记值越小的越先布线。(越先入队的越先布线)

我们假设对于标记值为 n 的点该结论成立,我们只需要证明从标记值为 n 的点出发,找到的标记值为 n+1 的点确实最短就可以了。

我们考察标记值 n 周围的可布线点,可以分为两类:已布线点和未布线点。

对于未布线的点:由布线规则可知,所有标记值 < n 点都已经布线完毕,点未被布线的唯一原因是任何一个标记值 < n 的点都无法与它相邻(到不了或者需要付出更大的代价才能到),所以该点只能通过点 n 或者相邻的标记值同样为 n 的点与起点联通,从而取得最小值,故对标记值为 n+1 的点结论同样成立。

因此该结论对于任意标记值的点都成立。

或者,一句话说就是迷宫格子形成了一颗BFS树,事实上我们已经把所有更短的路径都search出来了。所以不可能有更短的。

C++ 代码

#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <queue> using namespace std;
#define MAX 6 struct Point {
int x;
int y;
int len;
Point* pre; Point(): len(), pre() {}
Point(int x, int y): x(x), y(y), len(), pre() {}
void setPoint(int x, int y) {
this->x = x;
this->y = y;
}
}; queue<Point> mark;
void test(Point (*p)[MAX]); bool work(Point& q, Point& e, int (*map)[MAX], Point (*p)[MAX]) {
int x, y;
// up
if ((x=q.x-) >= && map[x][y=q.y] != && p[x][y].len == ) {
p[x][y].len = q.len + ;
p[x][y].pre = &q;
if (x == e.x && y == e.y) {
return true;
} else {
mark.push(p[x][y]);
}
}
// down
if ((x=q.x+) < MAX && map[x][y=q.y] != && p[x][y].len == ) {
p[x][y].len = q.len + ;
p[x][y].pre = &q;
if (x == e.x && y == e.y) {
return true;
} else {
mark.push(p[x][y]);
}
}
// left
if ((y=q.y-) >= && map[x=q.x][y] != && p[x][y].len == ) {
p[x][y].len = q.len + ;
p[x][y].pre = &q;
if (x == e.x && y == e.y) {
return true;
} else {
mark.push(p[x][y]);
}
}
// right
if ((y=q.y+) < MAX && map[x=q.x][y] != && p[x][y].len == ) {
p[x][y].len = q.len + ;
p[x][y].pre = &q;
if (x == e.x && y == e.y) {
return true;
} else {
mark.push(p[x][y]);
}
}
return false;
} void f(int (*map)[MAX], Point& s, Point& e, bool& k, Point (*p)[MAX]) {
mark.push(s);
int flag = false;
while (mark.size() != && !flag) { // 终止条件:找遍所有点都没找到终点&找到终点
flag = work(mark.front(), e, map, p);
mark.pop();
test(p); // 输出布线情况
}
k = flag;
} void test(Point (*p)[MAX]) { // 输出布线情况
for (int i = ; i != MAX; ++i) {
for (int j = ; j != MAX; ++j) {
printf("%d ", p[i][j].len);
}
cout << endl;
}
cout << endl;
} void printPath(Point& end) {
if (end.pre == ) {
printf("[%d][%d]\n", end.x, end.y);
return;
} else {
printPath(*(end.pre));
printf("[%d][%d]\n", end.x, end.y);
}
} int main()
{
int map[MAX][MAX] = { , , , , , ,
, , , , , ,
, , , , , ,
, , , , , ,
, , , , , ,
, , , , , }; Point s(, );
Point e(, ); bool k = false;
Point p[MAX][MAX];
p[s.x][s.y].len = ;
for (int i = ; i != MAX; ++i) {
for (int j = ; j != MAX; ++j) {
p[i][j].setPoint(i, j);
}
} // 初始化 f(map, s, e, k, p);
if (k) {
printf("MIN=%d\n", p[e.x][e.y].len);
printPath(p[e.x][e.y]);
} else {
printf("ERROR\n"); // 起点与终点不连通
} return ;
}

附件:迷宫问题

上面那道题用队列,这道用栈。

#include <stdio.h>
#define MAX 7 struct Point {
int x;
int y;
bool mark;
Point(): x(), y(), mark(false) {}
Point(int x, int y): x(x), y(y) {}
void setPosition(int x, int y) {
this->x = x;
this->y = y;
}
}; Point p[MAX][MAX];
bool seekPath(int (*map)[MAX], Point& s, Point& e) {
p[s.x][s.y].mark = true;
if (s.x == e.x && s.y == e.y) {
printf("MAP[%d][%d]\n", e.x, e.y);
return true;
} //printf("seekPath:1\n");
if (s.x+ < MAX && map[s.x+][s.y] != && !p[s.x+][s.y].mark && seekPath(map, p[s.x+][s.y], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:2\n");
if (s.x- >= && map[s.x-][s.y] != && !p[s.x-][s.y].mark && seekPath(map, p[s.x-][s.y], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:3\n");
if (s.y+ < MAX && map[s.x][s.y+] != && !p[s.x][s.y+].mark && seekPath(map, p[s.x][s.y+], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:4\n");
if (s.y- >= && map[s.x][s.y-] != && !p[s.x][s.y-].mark && seekPath(map, p[s.x][s.y-], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:5\n");
if (s.x+ < MAX && s.y+ < MAX && map[s.x+][s.y+] != && !p[s.x+][s.y+].mark && seekPath(map, p[s.x+][s.y+], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:6\n");
if (s.x+ < MAX && s.y- >= && map[s.x+][s.y-] != && !p[s.x+][s.y-].mark && seekPath(map, p[s.x+][s.y-], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:7\n");
if (s.x- >= && s.y+ < MAX && map[s.x-][s.y+] != && !p[s.x-][s.y+].mark && seekPath(map, p[s.x-][s.y+], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
//printf("seekPath:8\n");
if (s.x- >= && s.y- >= && map[s.x-][s.y-] != && !p[s.x-][s.y-].mark && seekPath(map, p[s.x-][s.y-], e)) {
printf("MAP[%d][%d]\n", s.x, s.y);
return true;
}
return false;
} void f(int (*map)[MAX], Point& s, Point& e) {
// chushihua
for (int i = ; i != MAX; ++i) {
for (int j = ; j != MAX; ++j) {
p[i][j].setPosition(i, j);
}
} // work
if (!seekPath(map, s, e)) {
printf("ERROR!\n");
}
//printf("f:runnable\n");
} int main()
{
int map[MAX][MAX] = { , , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , };
Point s(, );
Point e(, );
f(map, s, e);
//printf("main:runnable\n");
return ;
}

留着备用。

C++ 电路布线/最短路径问题的更多相关文章

  1. PCB Layout 中的高频电路布线技巧

    1.多层板布线 高频电路往往集成度较高,布线密度大,采用多层板既是布线所必须,也是降低干扰的有效手段.在PCB Layout阶段,合理的选择一定层数的印制板尺寸,能充分利用中间层来设置屏蔽,更好地实现 ...

  2. 算法java实现--动态规划--电路布线问题

    /* * dianlubuxian.java * Version 1.0.0 * Created on 2017年11月30日 * Copyright ReYo.Cn */ package reyo. ...

  3. 动态规划--电路布线(circuit layout)

    <算法设计与分析>  --王晓东 题目描述: 在一块电路板的上.下2端分别有n个接线柱.根据电路设计,要求用导线(i,a(i))将上端接线柱与下端接线柱相连,其中a(i)表示上端点i对应的 ...

  4. Eloquent JavaScript #07# Project: A Robot

    索引 Notes Excercise Measuring a robot Robot efficiency Persistent group 注释即笔记: const roads = [ " ...

  5. 布线问题&魔法花园_最短路径

    布线问题 问题描述:印刷电路板将布线区域划分成n×m个方格阵列,精确的电路布线问题要求确定连接方格a到方格b的最短布线方案:布线时,电路只能沿着直线或直角(方格)布线:已经布线的方格被锁定,即不允许其 ...

  6. PCB布线设计-模拟和数字布线的异同(转)

    工程领域中的数字设计人员和数字电路板设计专家在不断增加,这反映了行业的发展趋势.尽管对数字设计的重视带来了电子产品的重大发展,但仍然存在,而且还会一直存在一部分与模拟或现实环境接口的电路设计.模拟和数 ...

  7. 对Verilog 初学者比较有用的整理(转自它处)

    *作者: Ian11122840    时间: 2010-9-27 09:04                                                              ...

  8. 牛人的ACM经验 (转)

    一:知识点     数据结构:       1,单,双链表及循环链表       2,树的表示与存储,二叉树(概念,遍历)二叉树的                    应用(二叉排序树,判定树,博弈 ...

  9. js地址下拉列表中全职工作

    /******************************************************************* *输出全国各省辖市下拉列表项writeCitys() *输出企 ...

随机推荐

  1. 【巷子】---fetch---基本使用

    一.fetch fetch是一种XMLHttpRequest的一种替代方案,在工作当中除了用ajax获取后台数据外我们还可以使用fetch.axios来替代ajax 二.fetch的基本使用 1.np ...

  2. 推荐系统之最小二乘法ALS的Spark实现

    1.ALS算法流程: 初始化数据集和Spark环境----> 切分测试机和检验集------> 训练ALS模型------------> 验证结果-----------------& ...

  3. TCP 123=网络时间协议(NTP),Net Controller

    TCP 123=网络时间协议(NTP),Net Controller

  4. Cross-origin resource sharing JSON with Padding 同源策略 JSONP 为什么form表单提交没有跨域问题,但ajax提交有跨域问题? XMLHttpRequest and the Fetch API follow the same-origin policy 预检请求(preflight request)

    https://zh.wikipedia.org/wiki/跨来源资源共享 跨来源资源共享(CORS)是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略[1 ...

  5. Visibility from other objects

    php.net <?php class Test { private $foo; public function __construct($foo) { $this->foo=$foo; ...

  6. js之操作cookie

    js通过document.cookie获取所有的cookie信息, cookie在存储的格式是键值对,key=value每个键值对之间用; (分号和空格隔开). 添加cookie和修改cookie的值 ...

  7. JDK 伪共享解决方案

    关于AtomicReference AtomicReference是由JAVA5引入的,用于对一个对象引用进行原子操作,我们可以看到AtomicReference的实现是用CAS技术对引用进行指令级别 ...

  8. mysql 连接查询 join

    本文用到的表 CREATE TABLE `cls` ( `cls_id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, PRIMARY KEY (`cls ...

  9. 《深入理解Android内核设计思想》已陆续在全国各大书店及网上书店上市,感谢大家一直以来的支持~~

    <深入理解Android内核设计思想>已陆续在全国各大书店上市,电子书店也在陆续上架中(不断添加): 1. China-Pub 2. 京东 3. s=books&ie=UTF8&a ...

  10. 使用navicat mysql 远程连接数据库

    远程连接数据库,假设两台主机上都有navicat 客户端 远程主机A    ip地址:192.168.100.91  ,port  3306,数据库用户名 rootA   密码 123456A 本地主 ...