**
题意:
地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是出口,这两个位置保证为0。设计找到从入口到出口的最短路线。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)
思路:
一. bfs寻找最短路径类似树的按层遍历:1. 访问初始点(0,0),并将其标记为已访问过,vis[][]=1。 2. 访问(0,0)的所有未被访问过可到达的邻接点(在此处有小技巧,使用常量数组dx,dy拓展周边节点)并均标记为已访问过, 将这些点加入到队列中。注意:在判断是否可以加入队列时,注意条件限制,是否越界,是否可访问即为0,是否已经进入过队列,vis[][]=0。 3. 再按照队列中的次序,访问每一个顶点的所有未被访问过的邻接点, 并均标记为已访问过,加入到队列中,依此类推。 4. 直到到达终点或者图中所有和初始点(0,0)有路径相通的顶点都被访问过为止。
二. 输出最短路径:本题要求输出最短路径,在寻找最短路径的过程中,记录bfs遍历过程中节点的父亲节点,从终点开始回溯路径,依次将父节点放入栈中(先进后出),然后遍历栈中元素,输出最短路径。
总结:
寻找最短路径是bfs遍历的过程,在记录最短路径的过程中借助了父节点进行回溯。
代码:
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
struct point{
int x;
int y;
void set(int a,int b){x=a;y=b;}
};
int vis[5][5];//记录是否可到达
int a[5][5];
queue<point> q;
point fa[5][5];//记录父亲节点
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
void bfs(int x,int y)
{
point v;
v.set(x,y);
q.push(v);
vis[x][y]=1; //标记已到达
while(!q.empty())
{
point u=q.front();
q.pop();
for(int i=0;i<4;i++) //判断周围4个空格是否可走
{
point t;
int X=u.x+dx[i];
int Y=u.y+dy[i];
t.set(X,Y);
if(X>=0&&X<5&&Y>=0&&Y<5&&!vis[X][Y]&&!a[X][Y]) //未越界且未访问且可访问
{
vis[X][Y]=1; //标记已经过
q.push(t);
fa[X][Y]=u;
}
}
}
}
int main()
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
cin>>a[i][j];
bfs(0,0);
stack<point> lu; //记录bfs路径
point temp=fa[4][4]; //从终点往前遍历
while(!(temp.x==0&&temp.y==0))
{
lu.push(temp);
temp=fa[temp.x][temp.y];
}
cout<<"(0, 0)"<<endl;
while(!(lu.empty()))
{
cout<<"("<<lu.top().x<<", "<<lu.top().y<<")"<<endl;
lu.pop();
}
cout<<"(4, 4)"<<endl;
return 0;
}