题目353:3D dungeon

本文介绍了一道经典的三维迷宫问题,通过广度优先搜索算法寻找从起点到达终点的最短路径。提供了两种实现思路:深度优先搜索(超时)和广度优先搜索(AC)。对比了两种算法的时间复杂度及优缺点。

、##题目链接:
http://acm.nyist.net/JudgeOnline/problem.php?pid=353

描述

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.

输出

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!

样例输入

3 4 5
S….
.###.
.##..
###.#

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

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

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

样例输出

Escaped in 11 minute(s).
Trapped!

题目中文描述

简单翻译就是输入三维矩阵,第一行是L,R,C,分别代表着层数、每一层的行和列的数目。然后有L个R*C的矩阵,其中S代表起始点,E代表结束点,.代表可以走的路,#代表墙,问从S到E最少需要多少步。如果不能达到E,则输出Trapped!,如果可以,输出Escaped in # minute(s).(其中#代表最少需要的步数)

算法思想:

这道题是一道简单的广度搜索,只不过把一般的二维的扩展到了三维,算法思想其实是一样的,当然深度搜索也是可以的,但是会超时。由于前面AC过一道最少步数的题目(二维的),所以使用了深度搜索,结果超时,后来使用广度搜索,内存却超了,改进代码AC通过。
广度搜索的思想很简单,就是从起始结点开始搜索其相邻的六个方向(当然边界也需判断),如果遇到E,则退出,并返回步数,否则将其进队列,并将其标记为已访问。以此类推,直到队列为空。
深度搜索更简单,搜索当前点的六个方向,并更新当前点的状态为 ‘#’,表示已访问过,设为墙,注意搜索完后需要回溯,即将当前点的状态更新回来。

深搜源代码(超时)

/*
NYOJ(353):3D dungeon
Author:YangLinfeng
深度遍历
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int L, R, C, cnt;
char  map[35][35][35];
typedef struct{
    int l, r, c;
}Node,*PNode;
Node start;
void dfs(int x,int y,int z,int s)
{
    if (map[x][y][z] == '#' || map[x][y][z] == 0) return;//第一种退出条件
    if (map[x][y][z] == 'E')//第二种退出条件
    {
        cnt = min(cnt,s);
        return;
    }
    s++;
    map[x][y][z] = '#';//做标记,表示已访问
    dfs(x + 1, y, z, s);
    dfs(x - 1, y, z, s);
    dfs(x, y + 1, z, s);
    dfs(x, y - 1, z, s);
    dfs(x, y, z + 1, s);
    dfs(x, y, z - 1, s);
    map[x][y][z] = '.';//回溯
}
int main()
{
    while (cin >> L >> R >> C && L + R + C)
    {
        memset(map,0,sizeof(map));
        cnt = 9999999;
        for (int i = 1; i <= L; i++)
        {
            for (int j = 1; j <= R; j++)
            {
                for (int k = 1; k <= C; k++)
                {
                    cin >> map[i][j][k];
                    if (map[i][j][k] == 'S')
                        start.l = i, start.r = j, start.c = k;
                }
            }
        }

        dfs(start.l,start.r,start.c,0); 
        if (cnt != 9999999)
        {
            cout << "Escaped in " << cnt << " minute(s)." << endl;
        }
        else
            cout << "Trapped!" << endl;
    }
    return 0;
}

广搜源代码


/*
Author:YangLinfeng
NYOJ(353):3D dungeon
广度优先
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
char map[35][35][35];
int dir[6][3] = { { 0, 1, 0 }, { 0, 0, 1 }, { 0, -1, 0 }, { 0, 0, -1 }, { -1, 0, 0 }, { 1, 0, 0 } }; //六个方向
typedef struct{
    int l, r, c, step;
}Node, *PNode;
int visited[35][35][35];  //标记数组
queue<Node> Q;
Node e, curr;
int bfs(Node node)
{
    while (!Q.empty()) Q.pop();
    Q.push(node);
    while (!Q.empty())
    {
        e = Q.front();
        Q.pop();
        visited[e.l][e.r][e.c] = 1;
        //把e点相邻的六个方向且满足条件的点添加值队列中
        for (int i = 0; i < 6; i++)
        {
            int l, r, c;
            l = e.l + dir[i][0], r = e.r + dir[i][1], c = e.c + dir[i][2];
            if (!visited[l][r][c] && map[l][r][c] != '#' && map[l][r][c] != 0)
            {
                curr = { l, r, c, e.step + 1 };
                //当当前点是E点,退出(退出的第一种条件)
                if (map[curr.l][curr.r][curr.c] == 'E')
                {
                    return curr.step;
                }
                visited[curr.l][curr.r][curr.c] = 1;    
                Q.push(curr);
            }
        }
    }
    //当队列为空,表示搜索了所有路径还未找到E点,E点不可达,退出(退出的第二种条件)
    return -1;
}
int main()
{
    int L, R, C;
    Node start;
    while (cin >> L >> R >> C && (L + R + C))
    {
        memset(map, 0, sizeof(map)), memset(visited,0,sizeof(visited));
        for (int i = 1; i <= L; i++)
        {
            for (int j = 1; j <= R; j++)
            {
                for (int k = 1; k <= C; k++)
                {
                    cin >> map[i][j][k];
                    if (map[i][j][k] == 'S')
                        start.l = i, start.r = j, start.c = k, start.step = 0;
                }
            }
        }
        int ret = bfs(start);
        if (ret == -1)
            cout << "Trapped!" << endl;
        else
            cout << "Escaped in " << ret << " minute(s)." << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值