题目

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?

你被困在一个 L×R×C 的三维迷宫内,每分钟你只能够往上、下、左、右、前、后这六个方向的任意一个方向走一个单位。初始时你位于 S 位置,迷宫的出口为 E 位置,迷宫中标 # 的位置无法通过,并且你也不能够走出迷宫的边界。

你是否能够走出这个迷宫?如果能,求出最少的时间。

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。(L,R,C≤30)

输入有多组,以 L=R=C=0 结束。

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....
.###.
.##..
###.######
#####
##.##
##...#####
#####
#.###
####E1 3 3
S##
#E#
###

输出

11
-1

思路

题目为3d找路线,因为3d有些复杂,所以我选择先把2d写出来

转换为2d

设定输入的迷宫如下:

char[][] maze = new char[][]{{'S', '.', '.', '.'},{'.', '#', '#', '.'},{'.', '.', '.', '.'},{'#', '#', '.', '#'},{'#', '#', '.', 'E'}
};

visit用来存储是否访问过,dp用来存储到达当前节点的最少时间,为了方和dp初始化时的其他元素作区分,dp[0][0]做特殊处理,设置花费时间为1

每一个位置可以由上下左右四个位置移动得到,所以当前位置的最小值为min(dp[i - 1][j], dp[i + 1][j], dp[i][j - 1], dp[i][j + 1]) + 1

深度遍历,遍历完一个位置之后,又可以向上下左右四个方向移动,遇到#直接返回,否则就继续向下移动,通过getMin方法,来得到从上下左右四个方向的最短时间,直到遇到E结束

代码


public class t1_q2_Dungeon_Master_2d {public static void main(String[] args) {Sloution s = new Sloution();char[][] maze = new char[][]{{'S', '.', '.', '.'},{'.', '#', '#', '.'},{'.', '.', '.', '.'},{'#', '#', '.', '#'},{'#', '#', '.', 'E'}};int time = s.func(maze);System.out.println(time);}static class Sloution {char[][] maze;int[][] visit;int[][] dp;int r, c;int res = -1;public int func(char[][] maze) {this.maze = maze;this.r = maze.length;this.c = maze[0].length;this.visit = new int[r][c];this.dp = new int[r][c];bfs(0, 0);return res;}public void bfs(int i, int j) {if (i < 0 || i >= r || j < 0 || j >= c) return;if (maze[i][j] == '#') return;if (maze[i][j] == 'E') res = getMin(i, j);if (maze[i][j] != '#' && visit[i][j] == 0) {visit[i][j] = 1;if (i == 0 && j == 0) dp[i][j] = 1;else dp[i][j] = getMin(i, j) + 1;bfs(i + 1, j);bfs(i, j + 1);bfs(i - 1, j);bfs(i, j - 1);visit[i][j] = 0;}}int getMin(int i, int j) {int min = Integer.MAX_VALUE;if (i - 1 >= 0 && maze[i][j] != '#' && dp[i - 1][j] > 0) min = Math.min(dp[i - 1][j], min);if (i + 1 < r && maze[i][j] != '#' && dp[i + 1][j] > 0) min = Math.min(dp[i + 1][j], min);if (j - 1 >= 0 && maze[i][j] != '#' && dp[i][j - 1] > 0) min = Math.min(dp[i][j - 1], min);if (j + 1 < c && maze[i][j] != '#' && dp[i][j + 1] > 0) min = Math.min(dp[i][j + 1], min);return min;}}
}
  • 时间复杂度: O ( n 2 ) O(n^{2}) O(n2),其中 n 为数组中SE中间路径上.的数量,其中 0 < n < r ∗ c 0 < n < r * c 0<n<r∗c。我们可以找到一种最坏情况,即所有的点都是.,都可以继续去向后遍历。此时路径数为 O ( 2 n ) O(2^{n}) O(2n),且每条路径长度为 O(n),因此总时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)。

  • 空间复杂度: O ( r ∗ c ) O(r * c) O(r∗c),其中r为行数,c为列数。主要为栈空间、visit、dp的开销。

对于3d

2d维护了二维数组,所以三维就把数组换为3d,二维数组有上下左右四个方向,三维数组有上下左右前后四个方向

visit用来存储是否访问过,dp用来存储到达当前节点的最少时间,为了方和dp初始化时的其他元素作区分,dp[0][0][0]做特殊处理,设置花费时间为1

每一个位置可以由上下左右前后六个位置移动得到,所以当前位置的最小值为min(dp[i - 1][j][k], dp[i + 1][j][k], dp[i][j - 1][k], dp[i][j + 1][k], dp[i][j][k - 1], dp[i][j][k + 1] ) + 1

同上,深度遍历,遍历完一个位置之后,又可以向上下左右前后六个方向移动,遇到#直接返回,否则就继续向下移动,通过getMin方法,来得到从上下左右前后六个方向的最短时间,直到遇到E结束

代码


public class t1_q2_Dungeon_Master_3d {public static void main(String[] args) {Sloution s = new Sloution();char[][][] maze = new char[][][]{{{'S', '.', '.', '.', '.'},{'.', '#', '#', '#', '.'},{'.', '#', '#', '.', '.'},{'#', '#', '#', '.', '#'}},{{'#', '#', '#', '#', '#'},{'#', '#', '#', '#', '#'},{'#', '#', '.', '#', '#'},{'#', '#', '.', '.', '.'}},{{'#', '#', '#', '#', '#'},{'#', '#', '#', '#', '#'},{'#', '.', '#', '#', '#'},{'#', '#', '#', '#', 'E'}}};int time = s.func(maze);System.out.println(time);char[][][] maze1 = new char[][][]{{{'S', '#', '#'},{'.', '#', '#'},{'.', '#', 'E'}}};int time1 = s.func(maze1);System.out.println(time1);}static class Sloution {char[][][] maze;int[][][] visit;int[][][] dp;int res = -1;int l, r, c;public int func(char[][][] maze) {this.maze = maze;this.l = maze.length;this.r = maze[0].length;this.c = maze[0][0].length;this.visit = new int[l][r][c];this.dp = new int[l][r][c];bfs(0, 0, 0);return res;}public void bfs(int i, int j, int k) {if (i < 0 || i >= l || j < 0 || j >= r || k < 0 || k >= c) return;if (maze[i][j][k] == '#') return;if (maze[i][j][k] == 'E') {res = res == -1 ? getMin(i, j, k) : Math.min(res, getMin(i, j, k));}if (maze[i][j][k] != '#' && visit[i][j][k] == 0) {visit[i][j][k] = 1;if (i == 0 && j == 0 && k == 0) dp[i][j][k] = 1;else dp[i][j][k] = getMin(i, j, k) + 1;bfs(i + 1, j, k);bfs(i, j + 1, k);bfs(i, j, k + 1);bfs(i - 1, j, k);bfs(i, j - 1, k);bfs(i, j, k - 1);visit[i][j][k] = 0;}}int getMin(int i, int j, int k) {int min = Integer.MAX_VALUE;if (i - 1 >= 0 && maze[i][j][k] != '#' && dp[i - 1][j][k] > 0) min = Math.min(dp[i - 1][j][k], min);if (i + 1 < l && maze[i][j][k] != '#' && dp[i + 1][j][k] > 0) min = Math.min(dp[i + 1][j][k], min);if (j - 1 >= 0 && maze[i][j][k] != '#' && dp[i][j - 1][k] > 0) min = Math.min(dp[i][j - 1][k], min);if (j + 1 < r && maze[i][j][k] != '#' && dp[i][j + 1][k] > 0) min = Math.min(dp[i][j + 1][k], min);if (k - 1 >= 0 && maze[i][j][k] != '#' && dp[i][j][k - 1] > 0) min = Math.min(dp[i][j][k - 1], min);if (k + 1 < c && maze[i][j][k] != '#' && dp[i][j][k + 1] > 0) min = Math.min(dp[i][j][k + 1], min);return min;}}
}
  • 时间复杂度: O ( n 3 ) O(n^{3}) O(n3),其中 n 为数组中SE中间路径上.的数量,其中 0 < n < r ∗ c ∗ l 0 < n < r * c * l 0<n<r∗c∗l。我们可以找到一种最坏情况,即所有的点都是.,都可以继续去向后遍历。此时路径数为 O ( 3 n ) O(3^{n}) O(3n),且每条路径长度为 O(n),因此总时间复杂度为 O ( n 3 ) O(n^{3}) O(n3)。

  • 空间复杂度: O ( r ∗ c ∗ l ) O(r * c * l) O(r∗c∗l),其中r为行数,c为列数,l为深度。主要为栈空间、visit、dp的开销。

ps:
个人理解,有问题一起讨论

【专题一 简单搜索】2. Dungeon Master相关推荐

  1. kuangbin 专题一 简单搜索

    kuangbin 专题一 简单搜索 1.POJ1321棋盘问题[DFS] 代码 自己的想法 2.POJ2251Dungeon Master[三维空间BFS] 代码 自己的想法 3.POJ3278 Ca ...

  2. poj 3728 Catch That Cow ([kuangbin带你飞]专题一 简单搜索)

    题目大意:题目链接 就是给你N,K,每次有三种惭怍+1,-1,*2,,问多少次操作能到K 解题思路,搜索直接算,.,,,哎,啥时候这种垃圾搜索我能直接A 啊,太菜了 #include<cstdi ...

  3. [kuangbin带你飞]专题1 简单搜索 J - Fire! UVA - 11624

    题目: Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of t ...

  4. [kuangbin带你飞]专题一 简单搜索D - Fliptile(POJ 3279)

    题目大意 给一个N行M列的矩阵,值分别为0和1,每次你可以选择将一个变成相反状态,同时,它周围的四个数也会变为相反状态. 问:最少翻转多少次,可以将所有值都变成0 多个解,输出翻转次数最少的(若有次数 ...

  5. Catch That Cow POJ - 3278 [kuangbin带你飞]专题一 简单搜索

    Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. ...

  6. kuangbin专题一 简单搜索

    弱菜做了好久23333333........ 传送门: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105278#overview A ...

  7. [kuangbin带你飞]专题一 做题顺序与题解 【简单搜索】

    随便说点: 博主正在刷kuangbin专题的题目,初学者,没接触过什么算法,刷题的初衷是备战蓝桥杯,后来发现了算法资料大多是针对acm的,挑选kuangbin专题入门也是如此,毕竟这样分类看起来比较有 ...

  8. [kuanbin带我飞]简单搜索

    今天做了几道kuanbin专题,今天做的算是搜索入门题吧,不过自己确实做得够呛(黑脸) 迷宫问题 POJ - 3984 这道题就是bfs的模板题了,题意很简单,就找到从左上角到右下角的最短路线,这又让 ...

  9. Dungeon Master 地下城大师(BFS进阶)

    题目链接:2251 -- Dungeon Master 知道你看不懂题(手动滑稽):友情链接. 题意:找到从S到E的最少步数的路径,输出该步数,不过有意思的是这个类似迷宫问题不是二维的,是一个三维迷宫 ...

最新文章

  1. Linux C编程--进程介绍6--进程的各种标识
  2. 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频采样数据 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )
  3. php instanceof操作符
  4. SQL Server 2005异地备份
  5. 水晶报表图形位置_看了我用Excel做的年度报表,老板直夸好
  6. ftk学习记(button篇)
  7. 高度等于动态宽度(CSS流体布局)
  8. 人脸表情识别/人脸检测/ML/DL/图像处理博主
  9. Python3调用新浪微博API抓取数据
  10. pyltp的使用教程
  11. turtle库绘图:绘制QQ所有表情
  12. python判断火车票座位是否靠窗_Python查询火车票(一)
  13. 3年过去了!翟天临的微博又被写论文的研究生们喷了个底朝天...
  14. 山东法律学校97级计算机班,我校计算机学院97级计算机专业校友重聚母校
  15. 使用python制作读取示波器波形的GUI小工具
  16. Mathematica软件使用教程
  17. 51单片机OLED收银电子秤称重计价清零去皮金额累计HX711
  18. 爱丁堡大学计算机专业本科要求,爱丁堡大学计算机专业简单介绍及入学条件
  19. 使用vite创建vue3项目
  20. java 获取url 号后面,java获取url地址后缀名

热门文章

  1. 快逸v5报表工具软件的调度功能深受企业高管和员工的喜爱
  2. 跑步听音乐的最佳设备,无线蓝牙运动耳机推荐
  3. 代码随想录Day7| 454、383、15、18
  4. 泪目!字节跳动Android实习面试凉凉经,面试必备
  5. 矩阵点乘和叉乘的区别_矩阵点乘推荐算法预测图书推荐
  6. 一款分类超多的手机壁纸PHP源码
  7. scrapy与mongoDB完美结合
  8. 麦克风阵列技术-统计视角观察
  9. 论文分析<一>—— ECMP
  10. eslint原理入门