There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up (u), down (d), left (l) or right (r), but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. There is also a hole in this maze. The ball will drop into the hole if it rolls on to the hole.

Given the ball position, the hole position and the maze, find out how the ball could drop into the hole by moving the shortest distance. The distance is defined by the number of empty spaces traveled by the ball from the start position (excluded) to the hole (included). Output the moving directions by using 'u', 'd', 'l' and 'r'. Since there could be several different shortest ways, you should output the lexicographically smallest way. If the ball cannot reach the hole, output "impossible".

The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The ball and the hole coordinates are represented by row and column indexes.

Example 1

Input 1: a maze represented by a 2D array

0 0 0 0 0
1 1 0 0 1
0 0 0 0 0
0 1 0 0 1
0 1 0 0 0 Input 2: ball coordinate (rowBall, colBall) = (4, 3)
Input 3: hole coordinate (rowHole, colHole) = (0, 1) Output: "lul"
Explanation: There are two shortest ways for the ball to drop into the hole.
The first way is left -> up -> left, represented by "lul".
The second way is up -> left, represented by 'ul'.
Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is "lul".

Example 2

Input 1: a maze represented by a 2D array

0 0 0 0 0
1 1 0 0 1
0 0 0 0 0
0 1 0 0 1
0 1 0 0 0 Input 2: ball coordinate (rowBall, colBall) = (4, 3)
Input 3: hole coordinate (rowHole, colHole) = (3, 0)
Output: "impossible"
Explanation: The ball cannot reach the hole.

Note:

  1. There is only one ball and one hole in the maze.
  2. Both the ball and hole exist on an empty space, and they will not be at the same position initially.
  3. The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls.
  4. The maze contains at least 2 empty spaces, and the width and the height of the maze won't exceed 30.

这道题在之前的两道The Maze IIThe Maze的基础上又做了些改变,在路径中间放了个陷阱,让球在最小步数内滚到陷阱之中,此时返回的并不是最小步数,而是滚动的方向,用u, r, d, l 这四个字母来分别表示上右下左,而且在步数相等的情况下,让我们返回按字母排序小的答案。相对于迷宫二那题来说,难度是增加了一些,但我们还是可以借鉴之前那道题的思路,我们还是需要用一个二位数组dists,其中dists[i][j]表示到达(i,j)这个位置时需要的最小步数,我们都初始化为整型最大值,在后在遍历的过程中不断用较小值来更新每个位置的步数值。我们还需要用一个哈希表来建立每个位置跟滚到该位置的方向字符串之间的映射,这里我们用一个trick,将二维坐标转(i,j)为一个数字i*n+j,这实际上就是把二维数组拉成一维数组的操作,matlab中很常见的操作。还有需要注意的是,一滚到底的操作需要稍作修改,之前我们都是一直滚到墙里面或者界外才停止,然后做退一步处理,就是小球能滚到的位置,这里我们滚的时候要判断陷阱,如果滚到了陷阱,那么我们也停下来,注意这时候不需要做后退一步处理。然后我们还是比较当前步数是否小于dists中的原有步数,小于的话就更新dists,然后更新哈希表中的映射方向字符串,然后对于不是陷阱的点,我们加入队列queue中继续滚。另一点跟迷宫二不同的之处在于,这里还要处理另一种情况,就是当最小步数相等的时候,并且新的滚法的方向字符串的字母顺序要小于原有的字符串的时候,我们也需要更新哈希表的映射,并且判断是否需要加入队列queue中,参见代码如下:

解法一:

class Solution {
public:
string findShortestWay(vector<vector<int>>& maze, vector<int>& ball, vector<int>& hole) {
int m = maze.size(), n = maze[].size();
vector<vector<int>> dists(m, vector<int>(n, INT_MAX));
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
vector<char> way{'l','u','r','d'};
queue<pair<int, int>> q;
unordered_map<int, string> u;
dists[ball[]][ball[]] = ;
q.push({ball[], ball[]});
while (!q.empty()) {
auto t = q.front(); q.pop();
for (int i = ; i < ; ++i) {
int x = t.first, y = t.second, dist = dists[x][y];
string path = u[x * n + y];
while (x >= && x < m && y >= && y < n && maze[x][y] == && (x != hole[] || y != hole[])) {
x += dirs[i][]; y += dirs[i][]; ++dist;
}
if (x != hole[] || y != hole[]) {
x -= dirs[i][]; y -= dirs[i][]; --dist;
}
path.push_back(way[i]);
if (dists[x][y] > dist) {
dists[x][y] = dist;
u[x * n + y] = path;
if (x != hole[] || y != hole[]) q.push({x, y});
} else if (dists[x][y] == dist && u[x * n + y].compare(path) > ) {
u[x * n + y] = path;
if (x != hole[] || y != hole[]) q.push({x, y});
}
}
}
string res = u[hole[] * n + hole[]];
return res.empty() ? "impossible" : res;
}
};

下面这种写法是DFS的解法,可以看出来思路基本上跟上面的解法没有啥区别,写法上稍有不同,参见代码如下:

解法二:

class Solution {
public:
vector<vector<int>> dirs{{,-},{-,},{,},{,}};
vector<char> way{'l','u','r','d'};
string findShortestWay(vector<vector<int>>& maze, vector<int>& ball, vector<int>& hole) {
int m = maze.size(), n = maze[].size();
vector<vector<int>> dists(m, vector<int>(n, INT_MAX));
unordered_map<int, string> u;
dists[ball[]][ball[]] = ;
helper(maze, ball[], ball[], hole, dists, u);
string res = u[hole[] * n + hole[]];
return res.empty() ? "impossible" : res;
}
void helper(vector<vector<int>>& maze, int i, int j, vector<int>& hole, vector<vector<int>>& dists, unordered_map<int, string>& u) {
if (i == hole[] && j == hole[]) return;
int m = maze.size(), n = maze[].size();
for (int k = ; k < ; ++k) {
int x = i, y = j, dist = dists[x][y];
string path = u[x * n + y];
while (x >= && x < m && y >= && y < n && maze[x][y] == && (x != hole[] || y != hole[])) {
x += dirs[k][]; y += dirs[k][]; ++dist;
}
if (x != hole[] || y != hole[]) {
x -= dirs[k][]; y -= dirs[k][]; --dist;
}
path.push_back(way[k]);
if (dists[x][y] > dist) {
dists[x][y] = dist;
u[x * n + y] = path;
helper(maze, x, y, hole, dists, u);
} else if (dists[x][y] == dist && u[x * n + y].compare(path) > ) {
u[x * n + y] = path;
helper(maze, x, y, hole, dists, u);
}
}
}
};

类似题目:

The Maze II

The Maze

参考资料:

https://discuss.leetcode.com/topic/77116/bfs-solution-using-a-queue

https://discuss.leetcode.com/topic/77074/clear-java-accepted-dfs-solution-with-explanation

https://discuss.leetcode.com/topic/77474/similar-to-the-maze-ii-easy-understanding-java-bfs-solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] The Maze III 迷宫之三的更多相关文章

  1. [LeetCode] 499. The Maze III 迷宫 III

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  2. [LeetCode] The Maze II 迷宫之二

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  3. [LeetCode] House Robber III 打家劫舍之三

    The thief has found himself a new place for his thievery again. There is only one entrance to this a ...

  4. Leetcode: The Maze III(Unsolved Lock Problem)

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  5. [LeetCode] 505. The Maze II 迷宫 II

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  6. [LeetCode] The Maze 迷宫

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  7. [LeetCode] 505. The Maze II 迷宫之二

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  8. Leetcode: The Maze II

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  9. 3299: [USACO2011 Open]Corn Maze玉米迷宫

    3299: [USACO2011 Open]Corn Maze玉米迷宫 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 137  Solved: 59[ ...

随机推荐

  1. 对lua表中数据按一定格式处理,循环

    function putStartCard(handCard) function dataDeal(array,a,b,c) cclog("进入datadeal=============== ...

  2. web语义化之SEO和ARIA

    在快速理解web语义化的时候,只知道web语义化有利于SEO和便于屏幕阅读器阅读,但并不知道它是如何有利于SEO和便于阅读器阅读的,带着这个疑问,进行了一番探索总结. SEO 什么是SEO? SEO( ...

  3. spring框架学习笔记5:SpringAOP示例

    1.导包: 导入spring中的这两个包 再导入其他包(网上下载): 2.准备目标对象: package service; public class UserServiceImpl implement ...

  4. Android开发简易教程

    Android开发简易教程 Android 开发因为涉及到代码编辑.UI 布局.打包等工序,有一款好用的IDE非常重要.Google 最早提供了基于 Eclipse 的 ADT 作为开发工具,后来在2 ...

  5. 实现mypwd

    1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd 提交过程博客的链接 代码如图

  6. 《Language Implementation Patterns》之 增强解析模式

    上一章节讲述了基本的语言解析模式,LL(k)足以应付大多数的任务,但是对一些复杂的语言仍然显得不足,已付出更多的复杂度.和运行时效率为代价,我们可以得到能力更强的Parser. Pattern 5 : ...

  7. 用python实现简单购物车功能

    all_asset = 0 i1 = input("请输入总资产:") all_asset = int(i1) goods = [ {'name':'电脑','price':199 ...

  8. idea搭建springdata+mongodb+maven+springmvc

    idea搭建springdata+mongodb+maven+springmvc 今天我们来学习一下SpringData操作MongoDB. 项目环境:IntelliJ IDEA2017+maven3 ...

  9. 关于 Bootstrap的知识

    Bootstrap是简单.灵活的用于搭建WEB页面的HTML.CSS.Javascript的工具集.Bootstrap基于HTML5和CSS3,具有漂亮的设计.友好的学习曲线.卓越的兼容性,还有12列 ...

  10. 详解k8s一个完整的监控方案(Heapster+Grafana+InfluxDB) - kubernetes

    1.浅析整个监控流程 heapster以k8s内置的cAdvisor作为数据源收集集群信息,并汇总出有价值的性能数据(Metrics):cpu.内存.网络流量等,然后将这些数据输出到外部存储,如Inf ...