[kuangbin]专题一 简单搜索 Dungeon Master POJ - 2251【BFS】

【题目描述】
You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides. Is an escape possible? If yes, how long will it take?
你被困在一个三维地牢中,需要找到一条最快的路离开。地牢由立方体组成,这些立方体可能被岩石填充。每次向前后左右上下移动需要花费一分钟。你不能对角移动并且迷宫的四周都是坚硬的岩石。请问是否有可能逃离?如果有可能,需要花费多久?

【输入】
The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size). L is the number of levels making up the dungeon. R and C are the number of rows and columns making up the plan of each level. Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a ‘#’ and empty cells are represented by a ‘.’. Your starting position is indicated by ‘S’ and the exit by the letter ‘E’. There’s a single blank line after each level. Input is terminated by three zeroes for L, R and C.
输入由若干个地牢组成,每个地牢的描述以包含三个整数L、R和C的一行开始(都限制在30的大小)。L是组成地牢的层数,R和C是组成每层地牢的行数和列数。后面跟着L块R行每行包含C个字符。每个字符都描述地牢的一个单元格。充满岩石的单元格用‘#’表示,空单元格用‘.’表示。起始位置用“S”表示,离开位置用字母“E”表示。在每层输入之后有一个空行。对于L、R和C,输入由三个零终止。

【输出】
Each maze generates one line of output. If it is possible to reach the exit, print a line of the form
Escaped in x minute(s).
where x is replaced by the shortest time it takes to escape.
If it is not possible to escape, print the line
Trapped!
每个迷宫输出一行,如果可能到达出口,以Escaped in x minute(s).的形式输出,其中x用离开迷宫最短的时间代替。如果不可能离开,输出Trapped!

【样例输入】
3 4 5
S…
.###.
.##…
###.#

#####
#####
##.##
##…

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0

【样例输出】
Escaped in 11 minute(s).
Trapped!

题目链接:https://cn.vjudge.net/problem/POJ-2251

一般搜索迷宫最短路径用bfs较为常见,dfs一般容易超时。

以下为TLE的dfs代码

#include <iostream>
#include <cstring>
using namespace std;
static const int MAXN=30;
char mp[MAXN+2][MAXN+2][MAXN+2];
bool vis[MAXN+2][MAXN+2][MAXN+2];
int dx[]={1,-1,0,0,0,0};
int dy[]={0,0,1,-1,0,0};
int dz[]={0,0,0,0,1,-1};
int l,r,c,minstep;
bool check(int level,int row,int column)
{
    if(0<=level && level<l && 0<=row && row<r && 0<=column && column<c && !vis[level][row][column] && mp[level][row][column]!='#')
        return true;
    return false;
}
void dfs(int l,int r,int c,int step)
{
    if(mp[l][r][c]=='E')
    {
        if(step<minstep)
            minstep=step;
        return;
    }
    if(step>=minstep)
        return;
    for(int i=0;i<6;i++)
    {
        if(check(l+dz[i],r+dx[i],c+dy[i]))
        {
            vis[l+dz[i]][r+dx[i]][c+dy[i]]=true;
            dfs(l+dz[i],r+dx[i],c+dy[i],step+1);
            vis[l+dz[i]][r+dx[i]][c+dy[i]]=false;
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    while(cin>>l>>r>>c && l && r && c)
    {
        minstep=0x7fffffff;
        memset(mp,0,sizeof(mp));
        memset(vis,false,sizeof(vis));
        for(int i=0;i<l;i++)
            for(int j=0;j<r;j++)
                cin>>mp[i][j];
        for(int i=0;i<l;i++)
            for(int j=0;j<r;j++)
                for(int k=0;k<c;k++)
                    if(mp[i][j][k]=='S')
                        dfs(i,j,k,0);
        if(minstep==0x7fffffff)
            cout<<"Trapped!"<<endl;
        else
            cout<<"Escaped in "<<minstep<<" minute(s)."<<endl;        
    }
    return 0;
}

以下为AC的bfs代码:

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
static const int MAXN=30;
char mp[MAXN+2][MAXN+2][MAXN+2];
bool vis[MAXN+2][MAXN+2][MAXN+2];//用来标记已经搜索过的单元格
int dx[]={1,-1,0,0,0,0};
int dy[]={0,0,1,-1,0,0};
int dz[]={0,0,0,0,1,-1};
int l,r,c;
struct Node{
    int l,r,c,step;
};
bool check(Node node)//判断是否越界,该单元格是否可走,是否被走过
{
    if(0<=node.l && node.l<l && 0<=node.r && node.r<r && 0<=node.c && node.c<c && !vis[node.l][node.r][node.c] && mp[node.l][node.r][node.c]!='#')
        return true;
    return false;
}
void bfs(Node node)
{
    queue<Node> Q;
    Node now,next;
    Q.push(node);
    vis[node.l][node.r][node.c]=true;
    while(!Q.empty())
    {
        now=Q.front();
        Q.pop();
        if(mp[now.l][now.r][now.c]=='E')//找到出口直接输出并退出搜索,后面的路径即使存在,步数也不会比前面的路径小
        {
            cout<<"Escaped in "<<now.step<<" minute(s)."<<endl;
            return;
        }
        for(int i=0;i<6;i++)
        {
            next.l=now.l+dz[i];
            next.r=now.r+dx[i];
            next.c=now.c+dy[i];
            next.step=now.step+1;
            if(check(next))
            {
                vis[next.l][next.r][next.c]=true;//标记该单元格被走过
                Q.push(next);//把该单元格入队
            }
        }
    }
    cout<<"Trapped!"<<endl;//搜索完成仍没有找到出口
    return;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    while(cin>>l>>r>>c && l && r && c)
    {
        memset(mp,0,sizeof(mp));
        memset(vis,false,sizeof(vis));
        for(int i=0;i<l;i++)
            for(int j=0;j<r;j++)
                cin>>mp[i][j];
        for(int i=0;i<l;i++)
            for(int j=0;j<r;j++)
                for(int k=0;k<c;k++)
                    if(mp[i][j][k]=='S')
                        bfs(Node{i,j,k,0});
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值