迷宫问题(BFS+记录路径+stack+回溯)

在这里插入图片描述
这道题如果说求最短路径的话到时很简单;但是记录路径,我就很懵逼了;
我想了半天也不知道怎么记录路径,结果百度一下,大佬们用的二维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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值