美文网首页
LeetCode #1036 Escape a Large Ma

LeetCode #1036 Escape a Large Ma

作者: air_melt | 来源:发表于2022-03-07 23:03 被阅读0次

    1036 Escape a Large Maze 逃离大迷宫

    Description:
    There is a 1 million by 1 million grid on an XY-plane, and the coordinates of each grid square are (x, y).

    We start at the source = [sx, sy] square and want to reach the target = [tx, ty] square. There is also an array of blocked squares, where each blocked[i] = [xi, yi] represents a blocked square with coordinates (xi, yi).

    Each move, we can walk one square north, east, south, or west if the square is not in the array of blocked squares. We are also not allowed to walk outside of the grid.

    Return true if and only if it is possible to reach the target square from the source square through a sequence of valid moves.

    Example:

    Example 1:

    Input: blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
    Output: false
    Explanation: The target square is inaccessible starting from the source square because we cannot move.
    We cannot move north or east because those squares are blocked.
    We cannot move south or west because we cannot go outside of the grid.

    Example 2:

    Input: blocked = [], source = [0,0], target = [999999,999999]
    Output: true
    Explanation: Because there are no blocked cells, it is possible to reach the target square.

    Constraints:

    0 <= blocked.length <= 200
    blocked[i].length == 2
    0 <= xi, yi < 10^6
    source.length == target.length == 2
    0 <= sx, sy, tx, ty < 10^6
    source != target
    It is guaranteed that source and target are not blocked.

    题目描述:
    在一个 10^6 x 10^6 的网格中,每个网格上方格的坐标为 (x, y) 。

    现在从源方格 source = [sx, sy] 开始出发,意图赶往目标方格 target = [tx, ty] 。数组 blocked 是封锁的方格列表,其中每个 blocked[i] = [xi, yi] 表示坐标为 (xi, yi) 的方格是禁止通行的。

    每次移动,都可以走到网格中在四个方向上相邻的方格,只要该方格 不 在给出的封锁列表 blocked 上。同时,不允许走出网格。

    只有在可以通过一系列的移动从源方格 source 到达目标方格 target 时才返回 true。否则,返回 false。

    示例 :

    示例 1:

    输入:blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
    输出:false
    解释:
    从源方格无法到达目标方格,因为我们无法在网格中移动。
    无法向北或者向东移动是因为方格禁止通行。
    无法向南或者向西移动是因为不能走出网格。

    示例 2:

    输入:blocked = [], source = [0,0], target = [999999,999999]
    输出:true
    解释:
    因为没有方格被封锁,所以一定可以到达目标方格。

    提示:

    0 <= blocked.length <= 200
    blocked[i].length == 2
    0 <= xi, yi < 106
    source.length == target.length == 2
    0 <= sx, sy, tx, ty < 10^6
    source != target
    题目数据保证 source 和 target 不在封锁列表内

    思路:

    BFS
    由于棋盘过大, 仅使用 BFS 找到两个点之间的通路可能会 TLE
    考虑到 blocked 最大只有 200 个点
    如果 target 和 source 可到达的点超过 200 个, 就不可能被围住
    所以可以在超过 200 时进行剪枝
    时间复杂度为 O(n ^ 2), 空间复杂度为 O(n ^ 2)

    代码:
    C++:

    class Solution 
    {
    public:
        bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) 
        {
            unordered_set<long> s, t, v;
            for (const auto& block : blocked) s.insert(block.front() * 1001L + block.back());
            return dfs(source.front(), source.back(), s, source, target, t) and dfs(target.front(), target.back(), s, target, source, v);
        }
    private:
        bool dfs(int x, int y, unordered_set<long>& s, vector<int>& source, vector<int>& target, unordered_set<long>& visited) 
        {
            if (x == target.front() and y == target.back()) return true;
            long hash = x * 1001L + y;
            if (s.count(hash) or visited.count(hash) or x < 0 or x > 999999 or y < 0 or y > 999999) return false;
            if (abs(source.front() - x) + abs(source.back() - y) > 200) return true;
            visited.insert(hash);
            return dfs(x + 1, y, s, source, target, visited) or dfs(x - 1, y, s, source, target, visited) or dfs(x, y + 1, s, source, target, visited) or dfs(x, y - 1, s, source, target, visited);
        }
    };
    

    Java:

    class Solution {
        public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
            Set<Long> set = new HashSet<>();
            for (int[] block : blocked) set.add(block[0] * 1001L + block[1]);
            return dfs(source[0], source[1], set, source, target, new HashSet<>()) && dfs(target[0], target[1], set, target, source, new HashSet<>());
        }
        
        private boolean dfs(int x, int y, Set<Long> set, int[] source, int[] target, Set<Long> visited) {
            if (x == target[0] && y == target[1]) return true;
            long hash = x * 1001L + y;
            if (set.contains(hash) || visited.contains(hash) || x < 0 || x > 999_999 || y < 0 || y > 999_999) return false;
            if (Math.abs(source[0] - x) + Math.abs(source[1] - y) > 200) return true;
            visited.add(hash);
            return dfs(x + 1, y, set, source, target, visited) || dfs(x - 1, y, set, source, target, visited) || dfs(x, y + 1, set, source, target, visited) || dfs(x, y - 1, set, source, target, visited);
        }
    }
    

    Python:

    class Solution:
        def isEscapePossible(self, blocked: List[List[int]], source: List[int], target: List[int]) -> bool:
            blocked = set(map(tuple, blocked))
            
            def dfs(x: int, y: int, target: List[int], seen: Set[tuple]) -> bool:
                if not (0 <= x < 10 ** 6 and 0 <= y < 10 ** 6) or (x, y) in blocked or (x, y) in seen: 
                    return False
                seen.add((x, y))
                if len(seen) > 20000 or [x, y] == target: 
                    return True
                return dfs(x - 1, y, target, seen) or dfs(x, y - 1, target, seen) or dfs(x + 1, y, target, seen) or dfs(x, y + 1, target, seen)
            return dfs(source[0], source[1], target, set()) and dfs(target[0], target[1], source, set())
    

    相关文章

      网友评论

          本文标题:LeetCode #1036 Escape a Large Ma

          本文链接:https://www.haomeiwen.com/subject/tnlnrrtx.html