题目描述
洪尼玛今天准备去寻宝,在一个n*n (n行, n列)的迷宫中,存在着一个入口、一些墙壁以及一个宝藏。由于迷宫是四连通的,即在迷宫中的一个位置,只能走到与它直接相邻的其他四个位置(上、下、左、右)。现洪尼玛在迷宫的入口处,问他最少需要走几步才能拿到宝藏?若永远无法拿到宝藏,则输出-1。
输入描述
多组测试数据。
每组数据输入第一行为正整数n,表示迷宫大小。
接下来n行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'#'表示该位置为墙壁,字符'S'表示该位置为入口,字符'E'表示该位置为宝藏,输入数据中只有这四种字符,并且'S'和'E'仅出现一次。
n≤1000。
输出描述
输出拿到宝藏最少需要走的步数,若永远无法拿到宝藏,则输出-1。
样例输入
5
S.#..
#.#.#
#.#.#
#...E
#....
样例输出
7
解题思路
变量解释:
1.首先可以先用2个二维数组来记录,一个用来记录输入的图形,一个用来记录那些结点是否访问过。
2.用一个数组来标记上下左右4个方向。
char a[1005][1005];//记录图形
int vis[1005][1005];//记录是否访问过
int dir[4][2]=
{-1,0,//左
1,0,//右
0,1,//上
0,-1//下
};
3.在定义一个结构体struct来定义某个点,包含了x和y。方便将点插入队列中。
struct Point{
int x;
int y;
};
首先我们要遍历一遍找出起始点和终点的坐标,分别设置为sx,sy;ex,ey; 并将起始点入队,设其为队首。
这是一个典型的bfs例题,我们可以用一个队列来记录一些点,每一次都取出队首元素,然后对其进行4个方向的探索,如果当vis[ex][ey]!=0的时候,代表已经找到终点,此时就推出程序,输出次数就行。(vis[ex][ey]代表的是从起始点到终点一共移动的步数)
源码如下:
// http://acm.fzu.edu.cn/problem.php?pid=2285
#include<iostream>
#include<queue>
#include<string.h>
#include<stdio.h>
using namespace std;
char a[1005][1005];//记录图形
int vis[1005][1005];//记录是否访问过
int dir[4][2]=
{-1,0,//左
1,0,//右
0,1,//上
0,-1//下
};
struct Point{
int x;
int y;
};
Point temp1,temp2;
queue<Point> Q;
int main(){
int n;
while(scanf("%d",&n)!=EOF){
// memset(a,0,sizeof(a));
// memset(vis,0,sizeof(vis));
int sx,sy;
int ex,ey;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
vis[i][j]=0;
}
for(int i=0;i<n;i++) scanf("%s",a[i]);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]=='S'){
sx=i;
sy=j;
}
else if(a[i][j]=='E'){
ex=i;
ey=j;
}
}
}
while(!Q.empty()){//清空队列
Q.pop();
}
vis[sx][sy]=1;
temp1.x=sx;
temp1.y=sy;
Q.push(temp1);
int flag=0;
while(!Q.empty()){
temp1=Q.front();
Q.pop();
for(int i=0;i<4;i++){
temp2.x=temp1.x+dir[i][0];
temp2.y=temp1.y+dir[i][1];
if(temp2.x>=0 && temp2.y >=0 && temp2.x<n && temp2.y<n && !vis[temp2.x][temp2.y] && a[temp2.x][temp2.y]!='#'){
vis[temp2.x][temp2.y]=vis[temp1.x][temp1.y]+1;
Q.push(temp2);
}
}
if(vis[ex][ey]!=0){
flag=1;//代表已经找到
break;//要及时退出去,否则可能不是最短的
}
}
if(flag){
cout<<vis[ex][ey]-1<<endl;
}
else
cout<<-1<<endl;
}
return 0;
}