华为迷宫问题 广度优先遍历 BFS

看了好多博客,终于弄懂了。。。。

某位大神的代码,我给他几乎每一行都来个注释,方便以后看微笑

广度优先搜索的优点是找出的第一条路径就是最短路径,所以经常用来搜索最短路径,思路和图的广度优先遍历一样,需要借助于队列。

具体步骤: 
1)从入口元素开始,判断它上下左右的邻边元素是否满足条件,如果满足条件就入队列;
2)取队首元素并出队列。寻找其相邻未被访问的元素,将其如队列并标记元素的前驱节点为队首元素。
3)重复步骤(2),直到队列为空(没有找到可行路径)或者找到了终点。最后从终点开始,根据节点的前驱节点找出一条最短的可行路径。



#include<iostream>
#include<queue>
#include<stack>
using namespace std;

struct point
{
	int x;
	int y;
};
int **Maze;  //Maze是一个指针,指向的数据是int 指针类型   全局变量 
point **Pre; // Pre是一个指针,指向的数据是point 指针类型          保存任意点在路径中的前一步  
point move_ori[4]={{-1,0},{0,-1},{0,1},{1,0}};//移动方向为 行数减1,列数减1,列数加1 行数加1,

void Create(int row,int column){  
        //创建迷宫,注意到用0表示可走,1表示墙,将整个输入的迷宫再用墙围着,处理的时候就不用特别注意边界问题  	
	int i,j;
	for( i=0;i<row+2;i++)
	{
		 Maze[i][0]=1;
		 Maze[i][column+1] = 1;  
	}
	for( j=0; j<column+2; j++)  
	{
		Maze[0][j] = 1;
		Maze[row+1][j] = 1;  
	}
	//接收正常的迷宫
	for( i=1;i<row+1;i++)
	{
		for( j=1;j<column+1;j++)
		{
			cin>>Maze[i][j];
		}        
	}
    }  



bool MazePath(int row,int column,int x,int y)  判断是否有路径从入口到出口,保存该路径(队列)  
{
	if(x==row && y==column) //输入的点就是终点
	{
		return true;
	}
	//创建队列,从(x,y)点开始,判断它上下左右的邻边元素是否有一个满足条件,如果满足条件就入队列;
	queue<point> q; //定义队列q;
	point now; //当前点,传进来的x,y就是当前点的坐标
    now.x=x;
	now.y=y;
	q.push(now); //初始的入点加入队列 
	Maze[now.x][now.y]=-1; //标记当前点已经访问过了
	while(!q.empty()) //队列不为空就不会跳出循环
	{
		now=q.front();//访问队首元素 
		q.pop();//删除队首元素
		cout<<"清除队列中的("<<now.x<<now.y<<") "<<endl;;
		for(int i=0;i<4;i++)//四个方向  取值为0 ,1 ,2  之前取成 1,2 ,3,4了
		{
			//往该方向走后能到达终点,则跳出循环,且返回ture 跳出函数体
			if(now.x+move_ori[i].x==row && now.y+move_ori[i].y==column)
			{
               Maze[now.x+move_ori[i].x][now.y+move_ori[i].y]=-1; //标记此点访问过了
			   Pre[row][column] = now; //标记到达Maze[now.x+move_ori[i].x][now.y+move_ori[i].y]这个点的前一个点,  但是 [row][column] 为什么是这个??
			   return true;
			}			        
			
			if(Maze[now.x+move_ori[i].x][now.y+move_ori[i].y]==0) //该方向不是墙,可以走通
		{
			//
			point temp; //下个位置  
			temp.x=now.x+move_ori[i].x;
			temp.y=now.y+move_ori[i].y;  //对原来的坐标进行改变,
			cout<<"move_ori[i].x="<<move_ori[i].x<<" move_ori[i].y="<<move_ori[i].y<<" "<<endl;
			q.push(temp); //将新加入的点压入队列当中
			Maze[temp.x][temp.y]=-1; //下一个位置标记为访问过   对其他点的下一步展示为墙
			Pre[temp.x][temp.y]=now;  // //保存任意点在路径中的前一步    保存走到当前点的前一点是什么,  用于之后输出路径。
		    cout<<"Pre["<<temp.x<<"]["<<temp.y<<"]=("<<now.x<<" "<<now.y<<") "<<endl;
		}
		}
		
	}//结束while
	return false;
}

//根据Pre输出最短路径
void PrintPath(int row,int column)
{
	stack<point> s; //定义栈 用于保存路径。 先入后出
	point temp;
	temp.x=row;
	temp.y=column;
	
	while(temp.x!=1|| temp.y!=1)
	{
		s.push(temp);
		temp=Pre[temp.x][temp.y];
		
	}
	//从栈中输出
	cout<<"(0,0)"<<endl; //(0,0在上一步是没有入栈的,需手动输出)
	while(!s.empty())
	{
		temp=s.top(); 访问栈顶
		cout<<"("<<temp.x-1<<","<<temp.y-1<<")"<<endl;
		s.pop();    //删除栈顶元素  及出栈。。。
	}
	cout<<endl;
}




int main()
{	
	int row,column;//迷宫的行数和列数
	cin>>row>>column;
	//初始化迷宫,cin
	Maze = new int*[row + 2];   //分配一个元素个数为row+2的数组,数组的元素为int型指针   *是在int后面,
	Pre= new point*[row+2];
	for(int i=0; i<row+2; i++){  
                Maze[i] = new int[column + 2];  //为maze(i)申请 列那么多个int   在Maze的第i个元素分配column+2个int元素的空间。其后可以使用p[i][0]到p[i][column-1]个元素
                Pre[i] = new point[column + 2];  //如果没有这个for循环的话,在Create迷宫的时候,会出错,相当于没有创建成功二维数组。
            }  
	  Create(row,column);
//寻找迷宫出口
 if(MazePath(row,column,1,1))  
    PrintPath(row,column);
	return 0;

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值