《数据结构、算法与应用C++语言描述》-队列的应用-电路布线问题

news2024/11/18 6:01:03

《数据结构、算法与应用C++语言描述》-队列的应用-电路布线问题

问题描述

在 迷宫老鼠问题中,可以寻找从迷宫入口到迷宫出口的一条最短路径。这种在网格中寻找最短路径的算法有许多应用。例如,在电路布线问题的求解中,一个常用的方法就是在布线区域设置网格,该网格把布线区域划分成nxm个方格,就像迷宫一样(如图 9-12a 所示)。一条线路从一个方格 a 的中心点连接到另一个方格 b 的中心点,转弯处可以采用直角,如图 9-12b 所示。已经有线路经过的方格被“封锁”,成为下一条线路的障碍。我们希望用a 和 b之间的最短路径来布线,以减少信号的延迟。
在这里插入图片描述

求解策略

a和b之间的最短路径需要在两个过程中确定。一个是距离标记过程,另一个是路径标记过程。在距离标记过程中,先从位置a开始,把从a可到达的相邻方格都标记为1(表示与a相距为1),然后把从编号为1的方格可到达的相邻方格都标记为2(表示与a相距为2)。这个标记过程继续下去,直至到达b或者没有可到达的相邻方格为止。图9-13a 显示了这种搜索过程的结果,其中 a=(3,2),b=(4,6)。图中的阴影部分是被封锁的方格。

一旦到达 b,b 的编号便是 b 与 a之间的距离(在图 9-13a 中,b上的标号为 9)。距离标记过程结束之后,路径标记过程开始。从方格 b 开始,首先移动到一个其编号比b的编号小1的相邻方格上。在图9-13a中,我们从b移到方格(5,6)。接下来,从方格(5,6)移到比当前编号小 1 的相邻位置上。重复这个过程,直至到达 a 为止。在图 9-13a 的例子中,从(5,6),然后移到(6,6)、(6,5)、(6,4)、(5,4),等等。图 9-13b 给出了所得到的路径,它是(3,2)和(4,6)之间的最短路径。注意,最短路径不是唯一的,(3,2)、(3,3)、(4,3)、(5,3)、(5,4)、(6,4)、(6,5)、(6,6)、(5,6)、(4,6)是另一条最短路径。
在这里插入图片描述

代码

#include <iostream>
#include <queue>
using namespace std;

/*用于存储迷宫地址的结构体*/
struct Position
{
    int row,  //行
    col;  //列
    Position() {}
    Position(int prow, int pcol):row(prow),col(pcol){}
    operator int() const { return row; }
    friend ostream& operator<<(ostream& out, const Position x)
    {
        out << "(" << x.row << "," << x.col << ")";
        return out;
    }
};
/*创建二维数组*/
template <class T>
bool make2dArray(T**& x, int numberOfRows, int numberOfColumns)
{
    try {
        //行指针
        x = new T * [numberOfRows];
        //为每一行分配内存
        for (int i = 0; i < numberOfRows; i++)
            x[i] = new int[numberOfColumns];
        return true;
    }
    catch (bad_alloc) { return false; }
}

/*遍历二维数组*/
template<class T>
void traverse2dArray(T**& x, int numberOfRows, int numberOfColumns)
{
    for (int i = 0; i < numberOfRows; i++)
    {
        for (int j = 0; j < numberOfColumns; j++)
        {
            cout.width(4);
            cout << x[i][j] << "  ";
        }
        cout << endl;
    }
}

/*电路布线问题全局变量*/
int** Grid;//二维方阵
int GridSize;//方阵大小
queue<Position> path;//记录路径的队列
/*电路布线---和迷宫老鼠问题有点像*/
/*方格元素为1表示为障碍,方格元素为0表示无障碍*/
/*方格标记为2表示是起点,方格标记为大于2的整数m表示该方格距离起点m-2步*/
void inputGridQueue()//输入迷宫
{
    cout << "Please enter the size of Grid-Matrix:";
    while (!(cin >> GridSize))
    {
        cin.clear();//清空标志位
        while (cin.get() != '\n')//删除无效的输入
            continue;
        cout << "Please enter the size of Grid-Matrix:";
    }
    //+2的原因是为了避免在处理内部位置和边界位置时存在差别
    make2dArray<int>(Grid, GridSize + 2, GridSize + 2);
    //初始化边界位置的数值
    for (int i = 0; i <= GridSize + 1; i++)
    {
        Grid[i][0] = 1;
        Grid[0][i] = 1;
        Grid[i][GridSize + 1] = 1;
        Grid[GridSize + 1][i] = 1;
    }
    //初始化迷宫
    for (int i = 1; i <= GridSize; i++)
        for (int j = 1; j <= GridSize; j++)
        {
            int positionij;
            cout << "Please enter Grid[" << i << "," << j << "]:";
            while (!(cin >> positionij))
            {
                cin.clear();//清空标志位
                while (cin.get() != '\n')//删除无效的输入
                    continue;
                cout << "Please enter Grid[" << i << "," << j << "]:";
            }
            Grid[i][j] = positionij;
        }
    cout << "The Grid = " << endl;
    traverse2dArray<int>(Grid, GridSize + 2, GridSize + 2);
}
bool findPathQueue(Position start,Position end)//寻找从起点到终点的最短路径,如找到返回true,如没找到则返回false
{
    if ((start.row == end.row) && (start.col == end.col))
        return true;
    //初始化偏移量
    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;//上
    Position here = start;
    Grid[start.row][start.col] = 2;//标记起点为2
    int numOfNbrs = 4;//一个方格的相邻位置数
    /*标记各个方格*/
    queue<Position> q;//将需要标记的方格入栈q
    Position nbr;//邻居方格
    while (true)
    {
        //给相邻位置做标记
        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)//只有方格为0时表示方格无障碍和未标记
            {
                Grid[nbr.row][nbr.col] = Grid[here.row][here.col] + 1;
                if ((nbr.row == end.row) && (nbr.col == end.col))
                    break;//如果标记到终点,则标记完成
                q.push(nbr);//把邻居结点插入队列,以备后面标记,也就是找邻居的邻居
            }
        }
        if ((nbr.row == end.row) && (nbr.col == end.col))
            break;//如果标记到终点,则标记完成
        if (q.empty())
            return false;//没有找到终点,则不可达,返回false
        here = q.front();//取队首元素作为下一节点,以备标记其邻居节点
        q.pop();//删除队首节点
    }

    /*标记完成,构造路径*/
    int pathLength = Grid[end.row][end.col] - 2;
    here = end;//从终点开始回溯
    for (int i = pathLength - 1; i >= 0; i--)
    {
        path.push(here);
        for (int j = 0; j < numOfNbrs; j++)//在周边寻找父节点
        {
            nbr.row = here.row + offset[j].row;
            nbr.col = here.col + offset[j].col;
            if (Grid[nbr.row][nbr.col] == i + 2)
                break;
        }
        here = nbr;
    }
    path.push(start);
    return true;
}
void outputPathQueue()//输出路径
{
    int i = 0;
    cout << "The path = ";
    while(!path.empty()){
        cout << path.front() << ", ";
        path.pop();
    }
    cout << endl;
}

void routingOfCircuit()//测试函数
{
    inputGridQueue();//输入迷宫
    /*输入起始值点和终点*/
    Position start, end;
    cout << "Please enter the start node:";
    while (!(cin >> start.row >> start.col))
    {
        cin.clear();//清空标志位
        while (cin.get() != '\n')//删除无效的输入
            continue;
        cout << "Please enter the start node:";
    }
    cout << "Please enter the end node:";
    while (!(cin >> end.row >> end.col))
    {
        cin.clear();//清空标志位
        while (cin.get() != '\n')//删除无效的输入
            continue;
        cout << "Please enter the end node:";
    }
    findPathQueue(start, end);//寻找最短路径,如找到返回true,如没找到则返回false
    outputPathQueue();//输出路径
}

int main()
{
    cout << "电路布线问题********************" << endl;
    routingOfCircuit();

    return 0;
}

运行结果

C:\Users\15495\Documents\Jasmine\Work\coding\cmake-build-debug\coding.exe
鐢佃矾甯冪嚎闂********************
Please enter the size of Grid-Matrix:7
Please enter Grid[1,1]:0
Please enter Grid[1,2]:0
Please enter Grid[1,3]:1
Please enter Grid[1,4]:0
Please enter Grid[1,5]:0
Please enter Grid[1,6]:0
Please enter Grid[1,7]:0
Please enter Grid[2,1]:0
Please enter Grid[2,2]:0
Please enter Grid[2,3]:1
Please enter Grid[2,4]:1
Please enter Grid[2,5]:0
Please enter Grid[2,6]:0
Please enter Grid[2,7]:0
Please enter Grid[3,1]:0
Please enter Grid[3,2]:0
Please enter Grid[3,3]:0
Please enter Grid[3,4]:0
Please enter Grid[3,5]:1
Please enter Grid[3,6]:0
Please enter Grid[3,7]:0
Please enter Grid[4,1]:0
Please enter Grid[4,2]:0
Please enter Grid[4,3]:0
Please enter Grid[4,4]:1
Please enter Grid[4,5]:1
Please enter Grid[4,6]:0
Please enter Grid[4,7]:0
Please enter Grid[5,1]:1
Please enter Grid[5,2]:0
Please enter Grid[5,3]:0
Please enter Grid[5,4]:0
Please enter Grid[5,5]:1
Please enter Grid[5,6]:0
Please enter Grid[5,7]:0
Please enter Grid[6,1]:1
Please enter Grid[6,2]:1
Please enter Grid[6,3]:1
Please enter Grid[6,4]:0
Please enter Grid[6,5]:0
Please enter Grid[6,6]:0
Please enter Grid[6,7]:0
Please enter Grid[7,1]:1
Please enter Grid[7,2]:1
Please enter Grid[7,3]:1
Please enter Grid[7,4]:0
Please enter Grid[7,5]:0
Please enter Grid[7,6]:0
Please enter Grid[7,7]:0
The Grid =
   1     1     1     1     1     1     1     1     1
   1     0     0     1     0     0     0     0     1
   1     0     0     1     1     0     0     0     1
   1     0     0     0     0     1     0     0     1
   1     0     0     0     1     1     0     0     1
   1     1     0     0     0     1     0     0     1
   1     1     1     1     0     0     0     0     1
   1     1     1     1     0     0     0     0     1
   1     1     1     1     1     1     1     1     1
Please enter the start node:3 2
Please enter the end node:4 6
The path = (4,6), (5,6), (6,6), (6,5), (6,4), (5,4), (5,3), (5,2), (4,2), (3,2),

Process finished with exit code 0

离线等价类问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux进程(三)--进程切换命令行参数

继上回书Linux进程概念&#xff08;二&#xff09;--进程状态&进程优先级&#xff0c;我们在了解了Linux进程状态和优先级的概念&#xff0c;初步掌握了进程状态的相关知识&#xff0c;最终&#xff0c;我们以Linux进程的优先级&#xff0c;引出了一些其他的概念&#xff1…

非平稳信号分析和处理、STFT的瞬时频率研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

高校教务系统登录页面JS分析——华南理工大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

可以更改字体颜色的便签备忘录工具选择用哪个

日常添加笔记记录是一个非常好的习惯&#xff0c;通过笔记来记录一些重要的内容一方面可以帮助大家回顾过去的相关记录&#xff0c;另一方面如果记录的笔记是有关学习类的&#xff0c;还有助于大家随时查看记录的笔记。 多数时候记录笔记内容大家通常会选择一些比较方便易操作…

Spring中配置文件参数化

目录 一、什么是配置文件参数化 二、配置文件参数化的开发步骤 一、什么是配置文件参数化 配置文件参数化就是将Spring中经常需要修改的字符串信息&#xff0c;转移到一个更小的配置文件中。那么为什么要进行配置文件参数化呢&#xff1f;我们看一个代码 <bean id"co…

Chrome插件精选 — 扩展管理插件

Chrome实现同一功能的插件往往有多款产品&#xff0c;逐一去安装试用耗时又费力&#xff0c;在此为某一类型插件挑选出比较好用的一款或几款&#xff0c;尽量满足界面精致、功能齐全、设置选项丰富的使用要求&#xff0c;便于节省一个个去尝试的时间和精力。 1. 扩展管理器 下…

推荐《全职猎人》

电视动画《全职猎人》是由MADHOUSE公司制作的长篇电视动画&#xff0c;改编自日本漫画家富坚义博创作的同名漫画。该动画于2011年10月2日—2014年9月23日在日本电视网协议会首播&#xff0c;全148话。 剧场版动画《全职猎人&#xff1a;绯色的幻影》和《全职猎人&#xff1a;最…

Influence on Social media(素论+思维)

传送门&#xff1a;nefu_10-18 - Virtual Judge (vjudge.net) 思路&#xff1a; 每次给n个数&#xff0c;判断每个数的除数总数是否为奇素数。 对于整数&#xff1a;可质因子分解&#xff0c;,除数总数为&#xff08;i11&#xff09;*(i21)*(i31).... 若除数总数为奇素数&a…

golang笔记17--编译调试go源码

golang笔记17--编译调试go源码 前置条件编译源码在 fmt 包中加自定义函数说明 当前go语言越来越流行了&#xff0c;各大厂商都有加大go工程师的需求&#xff0c;作为go语言的学习者&#xff0c;我们除了要了解如何使用go语言外&#xff0c;也有必要了解一下如何编译、调试go源码…

双网关备份(bfd+VRRP+策略路由配置)企业网搭建

设备选型 vlan规划 Ip地址规划 产品名字 产品型号 设备命名 登录密码 路由器 Ar2220 Dianxin 123456 路由器 Ar2220 Dianxin 123456 路由器 Ar2220 Liantong 123456 路由器 Ar2220 R3 123456 交换机 S5700 S1 123456 交换机 S5700 S2 123456 交换机…

第十五章:输入输出流I/O

15.1&#xff1a;输入/输出流 文件类&#xff1a;File 字节流&#xff1a;InputStream&#xff1a;入 OutputStream&#xff1a;出 字符流&#xff1a;Reader&#xff1a;入 Writer&#xff1a;出 15.1.1 输入流 InputStream类是字节输入流的抽象类&#xff0c;所有字节流…

ubuntu终端命令行下如何使用NetworkManager(netplan)来配置wifi网络

最近在给家里折腾一个文件共享服务器给家里的小米摄像头保存监控视频用。树莓派太贵了&#xff0c;找来找去发现香橙派orangepi zero3 是最低成本的替代解决方案&#xff08;网络足够快&#xff0c;CPU的IO能力足够强&#xff09;&#xff0c;香橙派orangepi zero3的操作系统是…

《C语言图形界面-系统开发》专栏介绍 专栏目录

《C语言图形界面-系统开发》介绍及目录 基本介绍 本项目是一个基于EasyX图形库的C语言图书管理系统。 界面优美高级代码结构设计合理注释详尽清晰 本专栏是一个详尽到完全贴近C语言初学者的教程&#xff0c;完整代码 配套教程&#xff0c;完全不用担心学不会的问题。 项目展…

FPGA的通用FIFO设计verilog,1024*8bit仿真,源码和视频

名称&#xff1a;FIFO存储器设计1024*8bit 软件&#xff1a;Quartus 语言&#xff1a;Verilog 本代码为FIFO通用代码&#xff0c;其他深度和位宽可简单修改以下参数得到 reg [7:0] ram [1023:0];//RAM。深度1024&#xff0c;宽度8 代码功能&#xff1a; 设计一个基于FPGA…

EDUSRC--简单打穿某985之旅

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

AN动画基础——父子级关系

【AN动画基础——父子级关系】 父子级关系基础动画实战&#xff0c;行星的自转与公转 本篇内容&#xff1a;了解父子级关系 重点内容&#xff1a;父子级关系做动画 工 具&#xff1a;Adobe Animate 2022 父子级关系 在动画中&#xff0c;父子级关系通常用于控制对象之间的层次…

盘点数据采集中14种常见的反爬策略

引言 随着互联网的飞速发展, 爬虫技术不断演进, 为数据获取和信息处理提供了强大支持。然而, 滥用爬虫和恶意爬取数据的行为日益增多, 引发了反爬虫技术的兴起。在这场看似永无止境的 技术较量 中, 爬虫与反爬虫技术相互博弈、角力。本文将简单过下目前已知的几种反爬策略, 旨…

10.16课上,煎饼排序(选择排序实现),冒泡排序,快速排序

煎饼排序 第一步找剩余数组里的最大值&#xff0c;然后从头到这里翻转一次&#xff0c;这样最大值就到了开头&#xff0c;再把开头从当前结尾翻转一次&#xff0c;就把当前的最大值翻转到了最后 class Solution { public:vector<int> pancakeSort(vector<int>&am…

LCR 177. 撞色搭配

LCR 177. 撞色搭配 LCR 177. 撞色搭配 迷你游戏之寻找两个单身狗 int* sockCollocation(int* sockets, int socketsSize, int* returnSize) {int* arr (int*)malloc(2 * sizeof(int));int ret 0;for (int i 0; i < socketsSize; i){ret ^ sockets[i];}int pos 0;for…

软考系列(系统架构师)- 2018年系统架构师软考案例分析考点

试题一 软件架构&#xff08;非功能性需求、C/S 架构&#xff09; 【问题1】&#xff08;8分&#xff09; 在系统架构设计中&#xff0c;决定系统架构设计的非功能性需求主要有四类&#xff1a;操作性需求、性能需求、安全性需求和文化需求。请简要说明四类需求的含义。 (1) …