BFS之迷宫的最短路径
整体思想:简单来说就是步步为营,在现实生活中我们走迷宫无非两种方法,一种是拿一条线,不管三七二十一一路走下去,如果碰到障碍就返回,然后换一个方向走下去。另一种就是你每走一步 ,就观察你周围的情况,并把它记录下来,然后你走下一步的时候,就把你刚才记录的可以走的地方都试着走一遍,并记录周围的情况,以及标记我是从哪里走到这个位置的。重复以上步骤,最后按照这种方式你也可以找到出口,由于你每走到一个地方都会标记我是从哪里走到这个位置的,所以你可以 根据这个反推路径。
从编程的角度来看:
找到从起点到终点的最短路径其实就是一个建立队列的过程:
1.从终点开始,将其加入队列,设置距离为0;为什么不从起点开始,因为从起点开始的话,最后打印路径会比较麻烦。
2.从队列首端取出位置,将从这个位置能够到达的位置加入队列。
3.一轮探索至无法继续向队列中添加元素,即当前所在点的四周情况全部考虑完成后,循环第二步,直到将终点添加到队列中。说明此时已经找到了路径;
下面是具体代码,规定-1为起点,-2为终点,1为障碍。
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int m=4,n=3;
typedef pair<int,int> Position;
vector< vector<Position> > father(m,vector<Position>(n));//记录每个坐标的父节点
vector< vector<int> > Map(m,vector<int>(n));
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
bool in(int x,int y)
{
return 0<=x&&x<m&&0<=y&&y<n;
}
void Print_Path()//打印路径
{
int x=0,y=0;
while (x!=-2&&y!=-2)
{
cout<<x<<","<<y<<"\n";
int tem=x;
x=father[x][y].first;
y=father[tem][y].second;
}
}
void BFS()
{
queue<Position> q;
q.push(Position(m-1,n-1));
Map[m-1][n-1]=2;
father[m-1][n-1]=Position(-2,-2);
while (!q.empty())
{
Position tem=q.front();
q.pop();
for (int i=0;i<4;i++ )
{
Position now;
now.first=tem.first+dir[i][0];
now.second=tem.second+dir[i][1];
if(in(now.first,now.second))
{
if(Map[now.first][now.second]==-1)//如果到达起始位置,则说明存在最路径
{
father[now.first][now.second]=tem;
Print_Path();
return;
}
if(Map[now.first][now.second]==0)
{
father[now.first][now.second]=tem;
Map[now.first][now.second]=2;
q.push(now);
}
}
}
}
}
int main()
{
/*
-1 1 1
0 0 0
0 0 0
1 0 -2*/
for (int i=0;i<m;i++ )
{
for (int j=0;j<n;j++ )
{
cin>>Map[i][j];
}
}
BFS();
return 0;
}