寻找最短迷宫路径/电路布线问题(C++描述)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jeff_Winger/article/details/81989982

基本思想和寻找迷宫路径一致 https://mp.csdn.net/postedit/81980772 只是本文中找的是最短的路径,而这一思想也经常用于电路布线。主要方法是深度优先搜索和回溯法。

基本的方法是从起始点开始,对其 上,右,下,左四个方向的位置进行距离标定,如果在某一方向上没有障碍物则标定此方向距离起始点的距离,并且将此方向的位置放入队列等待下次从此位置继续开始标定。当然如果有障碍物则不标定。我们可以知道标识是否有障碍物的矩阵map还肩负着标识距离的重任,当然为了和1不发生冲突,距离值多加了2,这样很巧妙的利用了标识数组来标定距离,避免了重新开辟内存节省了内存。

从终点开始回溯,回溯的依据就是距离和标识点是差2的关系,其实这种关系从起始位置的设立map[start.first][start.second] = 2;就已经形成了。

代码如下:

#include<iostream>
#include<queue>
#include<vector>
#include<utility>
using namespace std;
bool findPath(vector<vector<int>>& mapIn,pair<int,int>& start,pair<int,int>& finish,vector<pair<int,int>>& path)
{
	if (mapIn.empty()) {
		return false;
	}
	int pathLength;
	if (start.first == finish.first&&start.second == finish.second){
		pathLength = 0;
		return true;
	}
	//方向设定
	vector<pair<int, int>> offset = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//分别代表右,下,左,上四个方向
    //初始化迷宫外面的障碍墙,这是为了处理边界位置时比较方便
	int n = mapIn.size();
	vector<int> vtemp(n + 2, 1);
	vector<vector<int>> map(n + 2, vtemp);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{//把之前的障碍搬到新的地图中
			map[i][j] = mapIn[i - 1][j - 1];
		}
	pair<int, int> here=start;
	map[start.first][start.second] = 2;  //1表示障碍,0表示可以通过,大于1表示相距起始点的距离(0+2)
	int numOfNbrs=4;
	//对可达到的位置做标记
	queue<pair<int, int>> q;
	pair<int, int> nbr;
	do {
		for (int i = 0; i < numOfNbrs; i++) {
			nbr.first = here.first + offset[i].first;
			nbr.second = here.second + offset[i].second;
			if (map[nbr.first][nbr.second] == 0) {//对可标记的位置做标记
				map[nbr.first][nbr.second] = map[here.first][here.second] + 1;
				if (nbr.first == finish.first&&nbr.second == finish.second) {//已经到达终点,结束
					break;
				}
				q.push(nbr);
			}
			
		}
		if (nbr.first == finish.first&&nbr.second == finish.second) {//已经到达终点,结束
			break;
		}
		//终点还没到达,是否可以移到之前的第一个nbr
		if (q.empty()) {//没有可以到达的路径
			return false;
		}
		here = q.front();
		q.pop();
	} while (true);
	pathLength = map[finish.first][finish.second] - 2;//最短的距离
	cout << pathLength << endl;
	//回溯追踪最短路径经过的点
	path.clear();
	path.resize(pathLength);
	here = finish;   //从终点开始追踪
	for (int j = pathLength - 1; j >= 0; j--)
	{
		path[j] = here;
		for (int i = 0; i < numOfNbrs; i++)
		{
			nbr.first = here.first + offset[i].first;
			nbr.second = here.second + offset[i].second;
			if (map[nbr.first][nbr.second] == j + 2) {
				break;//找到了满足条件的位置,而且满足条件的位置一定能找到
			}
		}
		here = nbr;//保存,下次继续从此点开始寻找
	}
	return true;
}
int main()
{
	vector<vector<int>> mapIn = { { 0,1,1,0,1,1 },
	                              { 0,0,1,0,1,0 },
	                              { 0,0,1,0,0,0 },
	                              { 1,0,0,0,1,0 },
	                              { 0,1,1,1,0,0 },
	                              { 0,1,1,1,0,0 } };
	pair<int, int> start(0,0);
	pair<int, int> finish(6, 6);
	vector<pair<int, int>> path;
	if (findPath(mapIn, start, finish, path)) {
		for (pair<int, int> pa : path)
		{//输出经过的位置,包含终点,不含起始点
			cout << pa.first << " " << pa.second << endl;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jeff_Winger/article/details/81989982