【Lintcode】788. The Maze II

题目地址:

https://www.lintcode.com/problem/the-maze-ii/description

给定一个二维数组,其表示一个迷宫, 0 0 代表空地, 1 1 代表障碍物,不含其它数字。再给定一个出发点和一个终点,题目保证出发点和终点都是空地。现在有一个小球从出发点出发,其可沿着四个方向直线滑行,直到遇到边界或者障碍物才能停下来。问是否存在一种滑行的可能,使得小球停在终点。

本质上是带权图求最短路,所以用Dijkstra算法。用一个优先队列记录小球每次滑行所滑到的目标点,然后再用一个数组来记录某个点是否之前滑到过。如果终点到了直接返回最短路径长度,否则继续尝试四个方向的滑行,直到所有可能的点都访问完毕为止。代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

public class Solution {
	// Pair是迷宫里的每个点的抽象出来的class,x和y代表坐标,dist代表离start的最少步数
    class Pair {
        int x, y, dist;
        
        Pair(int x, int y, int dist) {
            this.x = x;
            this.y = y;
            this.dist = dist;
        }
    }
    
    /**
     * @param maze:        the maze
     * @param start:       the start
     * @param destination: the destination
     * @return: the shortest distance for the ball to stop at the destination
     */
    public int shortestDistance(int[][] maze, int[] start, int[] destination) {
        // write your code here
        // 开一个优先队列,使得离start近的点先出队
        PriorityQueue<Pair> queue = new PriorityQueue<>((v1, v2) -> v1.dist < v2.dist ? -1 : 1);
        boolean[][] visited = new boolean[maze.length][maze[0].length];
        queue.offer(new Pair(start[0], start[1], 0));
        visited[start[0]][start[1]] = true;
        
        while (!queue.isEmpty()) {
            Pair cur = queue.poll();
            List<Pair> nexts = getNext(cur, maze, visited);
            for (Pair next : nexts) {
                if (next.x == destination[0] && next.y == destination[1]) {
                    return next.dist;
                }
                queue.offer(next);
                visited[next.x][next.y] = true;
            }
        }
        
        return -1;
    }
    // 返回从cur出发可以到达的且未被访问过的点
    private List<Pair> getNext(Pair cur, int[][] maze, boolean[][] visited) {
        int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        List<Pair> dest = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            int x = cur.x, y = cur.y, dist = 0;
            while (inBound(x, y, maze) && maze[x][y] != 1) {
                x += dirs[i][0];
                y += dirs[i][1];
                dist++;
            }
            x -= dirs[i][0];
            y -= dirs[i][1];
            dist--;
            
            if (!visited[x][y]) {
                dest.add(new Pair(x, y, cur.dist + dist));
            }
        }
        
        return dest;
    }
    
    private boolean inBound(int x, int y, int[][] maze) {
        return 0 <= x && x < maze.length && 0 <= y && y < maze[0].length;
    }
}

时间复杂度 O ( n log n ) O(n\log n) ,空间 O ( n ) O(n)

发布了354 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/105266863