There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction.

Given the ball's start position, the destination and the maze, find the shortest distance for the ball to stop at the destination. The distance is defined by the number of empty spaces traveled by the ball from the start position (excluded) to the destination (included). If the ball cannot stop at the destination, return -1.

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 start and destination coordinates are represented by row and column indexes.

Example 1

Input 1: a maze represented by a 2D array

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (4, 4) Output: 12
Explanation: One shortest way is : left -> down -> left -> down -> right -> down -> right.
The total distance is 1 + 1 + 3 + 1 + 2 + 2 + 2 = 12.

Example 2

Input 1: a maze represented by a 2D array

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (3, 2) Output: -1
Explanation: There is no way for the ball to stop at the destination.

Note:

  1. There is only one ball and one destination in the maze.
  2. Both the ball and the destination 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 both the width and height of the maze won't exceed 100.

490. The Maze 的拓展,490题只判断能否到达终点,而这道题让求出到达终点的最少步数。

要求最短的路径,普通的遍历dfs和bfs都是可以做的,但是求最短路径的话还是用Dijksra。这里相当于每个点有至多4条edge相连,每条edge的weight就是到墙之前的长度。

Java:

public class Solution {
public int shortestDistance(int[][] maze, int[] start, int[] destination) {
// base case
if(Arrays.equals(start, destination)) return 0; m = maze.length; n = maze[0].length; return shortestPath(maze, start, destination);
}
int m, n;
int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; private int shortestPath(int[][] maze, int[] start, int[] destination) {
// get the vertice has the minimum distance to start
PriorityQueue<Node> minHeap = new PriorityQueue<>((a, b) -> a.distance - b.distance);
minHeap.offer(new Node(start[0], start[1], 0)); // map that contains information of node: distance to start point
int[][] visited = new int[m][n];
for(int[] arr : visited) Arrays.fill(arr, Integer.MAX_VALUE); while(!minHeap.isEmpty()) {
Node cur = minHeap.poll();
// find the shortest path
if(cur.x == destination[0] && cur.y == destination[1]) return cur.distance; for(int[] dir : dirs) {
int nx = cur.x, ny = cur.y;
while(isInMaze(nx + dir[0], ny + dir[1]) && maze[nx + dir[0]][ny + dir[1]] != 1) {
nx += dir[0]; ny += dir[1];
}
int distance = cur.distance + Math.abs(nx - cur.x) + Math.abs(ny - cur.y);
if(visited[nx][ny] > distance) {
minHeap.offer(new Node(nx, ny, distance));
visited[nx][ny] = distance;
}
}
}
return -1;
} private boolean isInMaze(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
} class Node {
int x;
int y;
// distance to start point
int distance;
Node(int x, int y, int distance) {
this.x = x;
this.y = y;
this.distance = distance;
}
}
}

Python:

class Solution(object):
def findShortestWay(self, maze, ball, hole):
"""
:type maze: List[List[int]]
:type ball: List[int]
:type hole: List[int]
:rtype: str
"""
ball, hole = tuple(ball), tuple(hole)
dmap = collections.defaultdict(lambda: collections.defaultdict(int))
w, h = len(maze), len(maze[0])
for dir in 'dlru': dmap[hole][dir] = hole
for x in range(w):
for y in range(h):
if maze[x][y] or (x, y) == hole: continue
dmap[(x, y)]['u'] = dmap[(x - 1, y)]['u'] if x > 0 and dmap[(x - 1, y)]['u'] else (x, y)
dmap[(x, y)]['l'] = dmap[(x, y - 1)]['l'] if y > 0 and dmap[(x, y - 1)]['l'] else (x, y)
for x in range(w - 1, -1, -1):
for y in range(h - 1, -1, -1):
if maze[x][y] or (x, y) == hole: continue
dmap[(x, y)]['d'] = dmap[(x + 1, y)]['d'] if x < w - 1 and dmap[(x + 1, y)]['d'] else (x, y)
dmap[(x, y)]['r'] = dmap[(x, y + 1)]['r'] if y < h - 1 and dmap[(x, y + 1)]['r'] else (x, y)
bmap = {ball : (0, '')}
distance = lambda pa, pb: abs(pa[0] - pb[0]) + abs(pa[1] - pb[1])
queue = collections.deque([(ball, 0, '')])
while queue:
front, dist, path = queue.popleft()
for dir in 'dlru':
if dir not in dmap[front]: continue
np = dmap[front][dir]
ndist = dist + distance(front, np)
npath = path + dir
if np not in bmap or (ndist, npath) < bmap[np]:
bmap[np] = (ndist, npath)
queue.append((np, ndist, npath))
return bmap[hole][1] if hole in bmap else 'impossible'

Python: Dijkstra算法

class Solution(object):
def findShortestWay(self, maze, ball, hole):
"""
:type maze: List[List[int]]
:type ball: List[int]
:type hole: List[int]
:rtype: str
"""
ball, hole = tuple(ball), tuple(hole)
dmap = collections.defaultdict(lambda: collections.defaultdict(int))
w, h = len(maze), len(maze[0])
for dir in 'dlru': dmap[hole][dir] = hole
for x in range(w):
for y in range(h):
if maze[x][y] or (x, y) == hole: continue
dmap[(x, y)]['u'] = dmap[(x - 1, y)]['u'] if x > 0 and dmap[(x - 1, y)]['u'] else (x, y)
dmap[(x, y)]['l'] = dmap[(x, y - 1)]['l'] if y > 0 and dmap[(x, y - 1)]['l'] else (x, y)
for x in range(w - 1, -1, -1):
for y in range(h - 1, -1, -1):
if maze[x][y] or (x, y) == hole: continue
dmap[(x, y)]['d'] = dmap[(x + 1, y)]['d'] if x < w - 1 and dmap[(x + 1, y)]['d'] else (x, y)
dmap[(x, y)]['r'] = dmap[(x, y + 1)]['r'] if y < h - 1 and dmap[(x, y + 1)]['r'] else (x, y)
bmap = {ball : (0, '', ball)}
vset = set()
distance = lambda pa, pb: abs(pa[0] - pb[0]) + abs(pa[1] - pb[1])
while bmap:
dist, path, p = min(bmap.values())
if p == hole: return path
del bmap[p]
vset.add(p)
for dir in 'dlru':
if dir not in dmap[p]: continue
np = dmap[p][dir]
ndist = dist + distance(p, np)
npath = path + dir
if np not in vset and (np not in bmap or (ndist, npath, np) < bmap[np]):
bmap[np] = (ndist, npath, np)
return 'impossible'    

C++:

class Solution {
public:
int shortestDistance(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
int m = maze.size(), n = maze[0].size();
vector<vector<int>> dists(m, vector<int>(n, INT_MAX));
vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}};
queue<pair<int, int>> q;
q.push({start[0], start[1]});
dists[start[0]][start[1]] = 0;
while (!q.empty()) {
auto t = q.front(); q.pop();
for (auto d : dirs) {
int x = t.first, y = t.second, dist = dists[t.first][t.second];
while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == 0) {
x += d[0];
y += d[1];
++dist;
}
x -= d[0];
y -= d[1];
--dist;
if (dists[x][y] > dist) {
dists[x][y] = dist;
if (x != destination[0] || y != destination[1]) q.push({x, y});
}
}
}
int res = dists[destination[0]][destination[1]];
return (res == INT_MAX) ? -1 : res;
}
};

C++: DFS  

class Solution {
public:
vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}};
int shortestDistance(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {
int m = maze.size(), n = maze[0].size();
vector<vector<int>> dists(m, vector<int>(n, INT_MAX));
dists[start[0]][start[1]] = 0;
helper(maze, start[0], start[1], destination, dists);
int res = dists[destination[0]][destination[1]];
return (res == INT_MAX) ? -1 : res;
}
void helper(vector<vector<int>>& maze, int i, int j, vector<int>& destination, vector<vector<int>>& dists) {
if (i == destination[0] && j == destination[1]) return;
int m = maze.size(), n = maze[0].size();
for (auto d : dirs) {
int x = i, y = j, dist = dists[x][y];
while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == 0) {
x += d[0];
y += d[1];
++dist;
}
x -= d[0];
y -= d[1];
--dist;
if (dists[x][y] > dist) {
dists[x][y] = dist;
helper(maze, x, y, destination, dists);
}
}
}
};    

类似题目:

[LeetCode] 490. The Maze 迷宫

[LeetCode] 499. The Maze III 迷宫 III

All LeetCode Questions List 题目汇总

[LeetCode] 505. The Maze II 迷宫 II的更多相关文章

  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] 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 ...

  3. LeetCode 505. The Maze II

    原题链接在这里:https://leetcode.com/problems/the-maze-ii/ 题目: There is a ball in a maze with empty spaces a ...

  4. 老鼠走迷宫II

    转自:http://blog.csdn.net/holymaple/article/details/8636234 由于迷宫的设计,老鼠走迷宫的入口至出口路径可能不止一条,如何求出所有的路径呢? 解法 ...

  5. (╭ ̄3 ̄)╭ 小希的迷宫II

    (╭ ̄3 ̄)╭ 小希的迷宫II TimeLimit: 2000/1000 MS (Java/Others)  MenoryLimit: 65536/32768 K (Java/Others) 64-b ...

  6. [LeetCode] 95. Unique Binary Search Trees II(给定一个数字n,返回所有二叉搜索树) ☆☆☆

    Unique Binary Search Trees II leetcode java [LeetCode]Unique Binary Search Trees II 异构二叉查找树II Unique ...

  7. 【python】Leetcode每日一题-反转链表 II

    [python]Leetcode每日一题-反转链表 II [题目描述] 给你单链表的头节点 head 和两个整数 left 和 right ,其中 left <= right .请你反转从位置 ...

  8. 【LeetCode】522. Longest Uncommon Subsequence II 解题报告(Python)

    [LeetCode]522. Longest Uncommon Subsequence II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemin ...

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

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

随机推荐

  1. moviepy草码

    第一下. # coding=utf-8 from moviepy.editor import * from moviepy.video.tools.subtitles import Subtitles ...

  2. Java.io.tmpdir介绍

    System.getproperty(“java.io.tmpdir”)是获取操作系统缓存的临时目录,不同操作系统的缓存临时目录不一样, 在Windows的缓存目录为:C:\Users\登录用户~1\ ...

  3. Springboot整合通用mapper

    通用Mapper的分享使用 参考博客 Mybatis的通用mapper和Hibernate一样都实现了JPA接口,简化了数据库的操作 和Hibernate的对比 Hibernate和Mybatis都是 ...

  4. 《团队作业第三、四周》五阿哥小组Scrum 冲刺阶段---Day2

    <团队作业第三.四周>五阿哥小组Scrum 冲刺阶段---Day2 一.项目燃尽图 二.项目进展 20182310周烔今日进展: 主要任务一览:完成总博客的提交,制定接下来的计划,编写博客 ...

  5. C++中的hash_map和map的区别

    hash_map和map的区别在哪里?构造函数.hash_map需要hash函数,等于函数:map只需要比较函数(小于函数). 存储结构.hash_map采用hash表存储,map一般采用红黑树(RB ...

  6. git工具免密拉取、推送

    很苦恼每次都要配置明文密码才能正常工作 其实也可以配置成非明文 打开控制面板 →用户账号 管理 Windows凭证 对应修改响应网址即可  

  7. AD域与信任关系

    域与信任关系:信任关系分为两种,一种是林中信任关系,另一种是林之间的信任关系. 林中信任关系的特点: 注意:林中信任关系还可以分为两种:一种是父子信任,还有一种是树根信任. 父子信任:在同一个树域之中 ...

  8. PostgreSQL 一些比较好用的字符串函数

    最近刚接触到PostgreSQL数据库,发现很多功能比较强大的内置函数,特此记录下来.示例下次再补. 1.concat 字符串连接函数 2.concat_ws concat_ws函数连接可自定义分隔符 ...

  9. 实训作业5(lang、util)

    实验内容和原理: 1.将布尔型.整型.长整型.双精度型作为参数,实例化相应的包装类对象,并输出对象的数值. package 包装; public class integer { public stat ...

  10. 2-STM32+W5500+GPRS(2G)基础篇-(W5500-学习说明)

    https://www.cnblogs.com/yangfengwu/p/11220042.html 定版: 这一节先直接说明怎么把官方的源码应用在我做的这块开发板上 https://www.w550 ...