基本思想和寻找迷宫路径一致 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;
}