这道题如果说求最短路径的话到时很简单;但是记录路径,我就很懵逼了;
我想了半天也不知道怎么记录路径,结果百度一下,大佬们用的二维Node数组记录父节点,确实厉害!!!
首先来理解一下什么是BFS吧;
如图:
注意这里我自己给的节点编号顺序不能变哦;
那么BFS思路呢就是这样滴(建议这里自己手写一下理解):
首先把1节点进入队列;然后扫一遍1节点能到达的节点也就是2和3(依次进队),那么用一个数组去标记2,3已经走过了;
那么把1出队,然后扫描2所能到达的节点,也就是4,5(依次进队),然后book标记4,5节点表示走过了;然后2出队;
然后遍历3能到达的节点,也就是6(依次进队),那么标记6表示走过了,然后遍历4能到达的节点,因为6被标记了所以不能走到6了,同理5节点也一样;这道题的思路就是这样找的最短路径;(当然bfs经常会在细节处改变);
然后问题就来了,虽然我能写出bfs来,但是如何记录路径呢?
那么要解决这个问题,如果爱思考的我相信可以从上面的思路中有点想法了;就是每个节点记录他的父节点;比如:
3记录1,6记录3;那么最后用一个stack一直回溯就可以找出来最短路径了;
只不过这道题是把(x,y)映射为一个节点而已,仔细想了一下这个想法确实很厉害;
AC代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
using namespace std;
struct Node{//节点
int x,y;
};
queue<Node> q;//队列
int dir[][2]={{-1,0},{0,1},{1,0},{0,-1}};//四个方向
Node fa[6][6];//记录父节点(从坐标到对象)
int book[200][200];//标记
int maze[200][200];//迷宫
stack<Node> S;//栈
void bfs(){
book[0][0]=1;//标记第一个节点走过了
Node tt;
tt.x=0;tt.y=0;
q.push(tt);
while(q.size()){
Node t=q.front();q.pop();
Node ppp;
for(int i=0;i<4;i++){//遍历四个方向
ppp.x=t.x+dir[i][0],ppp.y=t.y+dir[i][1];
if(ppp.x>=0&&ppp.x<5&&ppp.y>=0&&ppp.y<5&&!book[ppp.x][ppp.y]&&maze[ppp.x][ppp.y]==0){//没越界+没标记过+能走
book[ppp.x][ppp.y]=1;//标记走过了(这里就是解释为4,5不能到6了因为6已经被标记了)
q.push(ppp);//进队
fa[ppp.x][ppp.y]=t;//这里很关键了,这里是记录头节点能到的下一个节点的坐标,然后用这个坐标去记录头结点(有点抽象,但是又感觉像连锁机关的样子,嘻嘻)
}
}
}
}
void Recall(){
Node t=fa[4][4];//这里从终点回溯回去
while(!(t.x==0&&t.y==0)){//这里不断回溯找最短路径
S.push(t);
t=fa[t.x][t.y];
}
}
void init(){//初始化
for(int i=0;i<5;i++){
for(int j=0;j<5;j++)scanf("%d",&maze[i][j]);
}
}
int main(){
init();
bfs();
Recall();
//cout<<S.size()<<endl;
printf("(%d, %d)\n",0,0);//因为起点是没有stack进去的
while(S.size()){
Node t=S.top();
S.pop();
printf("(%d, %d)\n",t.x,t.y);
}
printf("(%d, %d)\n",4,4);//因为回溯的时候终点是没有stack进去的
return 0;
}