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

来源:互联网 发布:音乐间谍类似软件 编辑:程序博客网 时间:2024/05/16 05:50

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

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

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

具体步骤: 
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;}}}//结束whilereturn 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;//初始化迷宫,cinMaze = 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;}


原创粉丝点击