福州大学【Problem 2285 迷宫寻宝】--bfs解题

题目描述

洪尼玛今天准备去寻宝,在一个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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值