C++ 电路布线/最短路径问题

本文介绍了使用C++解决电路布线的最短路径问题。通过二维数组表示地图,以0和1区分障碍物与可行路径。从起点开始,采用广度优先搜索(BFS)策略,逐步标记并更新最短路径,最终找到终点时其标记值即为最短距离。此外,还提及了一个类似迷宫问题的解决方案,但使用了栈而非队列。
摘要由CSDN通过智能技术生成
问题描述

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

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

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

 

问题分析

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

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

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

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

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

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

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

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

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

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

 

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(0), pre(0) {}
    Point(int x, int y): x(x), y(y), len(0), pre(0) {}
    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-1) >= 0 && map[x][y=q.y] != 1 && p[x][y].len == 0) {
        p[x][y].len = q.len + 1;
        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+1) < MAX && map[x][y=q.y] != 1 && p[x][y].len == 0) {
        p[x][y].len = q.len + 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值