题目:
定义一个二维数组:
int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, };
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0
Sample Output
(0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4)
题目大意:
有一个迷宫,要求探索能否到达终点,如果可以的话输出路径
算法:
bfs 队列
代码:
#include<bits\stdc++.h>
#include<cstdio>
#include<iostream>
using namespace std;
struct node
{
int x;
int y;
int f;
};
struct node que[2501]; //一共最多有2500个元素
int a[51][51],b[51][51]; //a是存储迷宫的数组 b是标记数组
void print(int s) //递归输出
{
if(que[s].f!=-1)
{
print(que[s].f);//根据查找前一个的位置来递归
cout<<"("<<que[s].x<<", "<<que[s].y<<")"<<endl;
}
}
int main()
{
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; //方向数组 用来遍历四个方向
int head,tail;
int i,j,k,p,q,tx,ty,flag;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
cin>>a[i][j]; //输入迷宫信息
head=tail=1;
que[tail].x=0;
que[tail].y=0; //迷宫起点入队
que[tail].f=-1; //起点的father标记为-1 便于递归输出路径时使用
tail++;
b[0][0]=1; //标记这个点已经走过
flag=0; //flag在判断终止时使用
while(head<tail)
{
for(k=0;k<4;k++)
{
tx=que[head].x+next[k][0];
ty=que[head].y+next[k][1]; //四个方向
if(tx<0||tx>4||ty<0||ty>4) continue; //越界
if(a[tx][ty]==0&&b[tx][ty]==0) //这个点之前没有走过 并且 是路
{
b[tx][ty]=1; //标记
que[tail].x=tx;
que[tail].y=ty;
que[tail].f=head; //入队
tail++;
}
if(tx==4&&ty==4)
{
flag=1;
break; //到达终点
}
}
if(flag==1) break;
head++; //这个点已经探索完了 出队
}
cout<<"(0, 0)"<<endl;
if(flag==1)
print(head);
cout<<"(4, 4)";
return 0;
}
解析:
这道题,要求输出路径,于是决定使用bfs算法,采用队列,可以存储路径。
que[].f 用来存储这个元素的父节点,也就是说-存储这个节点是从哪一个节点探索而来的。
当探索到终点后,使用自定义的递归print函数输出路径。
如果这个点的父亲不是-1(也就是代码最开始,起点入队时,标记的que[tail].f=-1)那么就递归他的父亲节点,知道这个元素的父亲节点是起点,那么就输出他本身,这也就是为什么要单独输出起点。
至于为什么单独输出终点坐标是因为: 在判断flag==1后就直接break了,没有进行head++。
说完了路径再来说 bfs 总的来说我对bfs的使用没有dfs的顺手
每探索完四个方向,这个时候就要出队,这个地方的出队并不是c++队列的真正出队,他还是存储在了原本的数组中,只是我们认为他已经出队了。