信息学奥赛一本通 1248:Dungeon Master | OpenJudge NOI 2.5 1253:Dungeon Master

【题目链接】

ybt 1248:Dungeon Master
OpenJudge NOI 2.5 1253:Dungeon Master

【题目翻译】

地牢城主

描述

你被困在一个3D地牢中,需要找到可以走出地牢的最快的一条路。地牢由方块单位组成,方块中可能有或没有填满岩石。向东、南、西、北、上或下移动一个单位需要花费1分钟。你不可以向对角线方向移动。整个迷宫外各个方向都被坚硬的岩石包围。
是否可能逃脱呢?如果可能,需要用多久?

输入

输入包括一个地牢数字。每个地牢以包括L,R与C(大小都小于等于30)三个整数的一行开始。
L是地牢的层数。
R与C是每层平面的行数和列数。
接下来是L块,每块有R行,每行C个字符。每个字符表示一个地牢的房间。一个装满岩石的房间由’#‘表示,空房间由’.‘表示。你的起始位置由’S’表示,出口是字母’E’。每一层后有一个空行。
输入以表示L、R与C的三个0为结尾。

输出

每个迷宫产生一行输出。如果可能到达出口,如下面的格式输出一行:
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!

来源

Ulm Local 1997

【题目考点】

1. 搜索 迷宫问题

【解题思路】

二维迷宫问题可以参考:1251:仙岛求药
该题为三维迷宫问题,解题方法与二维迷宫问题类似,只需要将设的地图数组、vis数组变为三维、结点中表示坐标的变量设为三个。起点、终点坐标都是三维的,移动方向变为东西南北上下6个方向。
注意:

  • 多组数据问题,要做数据清空。
  • 输入数据时,先按层遍历,而后按行、按列遍历。要清楚三维数组第1、2、3维分别对应什么。

【题解代码】

解法1:广搜
#include<bits/stdc++.h>
using namespace std;
#define N 35
char mp[N][N][N];//地图 (x,y,z):x行y列z层 
int l, r, c, ans;//l:层数 r:行数 c:列数  
int sx, sy, sz, ex, ey, ez;//(sx,sy,sz):起点位置  (ex,ey,ez):终点位置 
int dir[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};//方向数组
bool vis[N][N][N];//vis[i][j][k]:(i,j,k)位置是否已经访问过 
struct Node
{
    int x, y, z, t;//走到位置:(x,y,z),时间t 
    Node(){}
    Node(int a, int b, int c, int d):x(a),y(b),z(c),t(d){}
};
int bfs()//从(sx,sy,sz)出发进行广搜,如果能到达终点(ex,ey,ez),返回时间。否则返回-1 
{
    queue<Node> que;
    vis[sx][sy][sz] = true;
    que.push(Node(sx, sy, sz, 0));
    while(que.empty() == false)
    {
        Node u = que.front();
        que.pop();
        if(u.x == ex && u.y == ey && u.z == ez)
            return u.t;
        for(int i = 0; i < 6; ++i)
        {
            int x = u.x + dir[i][0], y = u.y + dir[i][1], z = u.z + dir[i][2];
            if(x >= 1 && x <= r && y >= 1 && y <= c && z >= 1 && z <= l && vis[x][y][z] == false && mp[x][y][z] != '#')
            {
                vis[x][y][z] = true;
                que.push(Node(x, y, z, u.t+1));
            }
        }
    }
    return -1;
}
int main()
{
    while(cin >> l >> r >> c)
    {
        if(l == 0 && r == 0 && c == 0)
            break;
        for(int z = 1; z <= l; ++z)//层 
            for(int x = 1; x <= r; ++x)//行 
                for(int y = 1; y <= c; ++y)//列 
                {
                    cin >> mp[x][y][z];
                    if(mp[x][y][z] == 'S')
                        sx = x, sy = y, sz = z;
                    else if(mp[x][y][z] == 'E')
                        ex = x, ey = y, ez = z;
                }
        memset(vis, 0, sizeof(vis));
        ans = bfs();//求到达终点的时间     
        if(ans == -1)
            cout << "Trapped!" << endl;
        else
            cout << "Escaped in " << ans <<" minute(s)." << endl;
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值