【算法】逃离大迷宫

题目信息

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

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

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

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

0 <= blocked.length <= 200

题目解析

很容易让人想到用dfs或bfs遍历所有格子,来确定能否到达终点,但此题的数据范围太大,10^6大概率会超时,所以需要另辟蹊径。

题目告诉我们blocked.length在0,200 , 所以说大部分的位置都是空的,可以走的,那什么情况下无法赶往目标方格呢,就是入口或出口被分别包围起来了。

那我们只要证明,入口和出口没有被包围,就可以说明一定可以从源点走到目标点的。

那么怎么确认有没有被包围,就是我们要解决的问题了:

由题目可知,blocked的大小最多只有200个,而大迷宫是个10^6 * 10^6的超大迷宫,所以最大面积只能是它作为一条斜边依赖于两个墙角。

如果你不能理解,代码里的MAX也是可以设置为200 * 200(甚至是1e5),假设了超过blocked的个数一倍的大小。

之后,利用bfs的方式,分别判断入口和出口有没有被包围即可!

代码

cpp 复制代码
class Solution {
public:
    int EDGE = 1e6 , MAX = 1e5;
    int BASE = 131;
    unordered_set<long long> set;
    int dir[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };

    bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& s, vector<int>& t) {
        int n = blocked.size();
        for(auto& p : blocked)
            set.insert(p[0]*BASE+p[1]);
        MAX = n * (n-1) / 2;
        return check(s,t) && check(t,s);
    }

    bool check(vector<int>& a, vector<int>& b){
        unordered_set<long long> vis;
        queue<pair<int,int> > q;
        q.push({a[0],a[1]});

        while(q.size() > 0 && vis.size() <= MAX){
            auto t = q.front();
            q.pop();
            int x = t.first, y = t.second;
            if(x == b[0] && y == b[1]) return true;

            vis.insert(x * BASE + y);
            for(int i = 0;i<4;i++){
                int nx = x + dir[i][0], ny = y + dir[i][1];
                if(nx < 0 || nx >= EDGE || ny < 0 || ny >= EDGE){
                    continue;
                }

                if(set.count(nx * BASE + ny)) continue;
                if(vis.count(nx * BASE + ny)) continue;

                q.push({nx , ny});
                vis.insert(nx * BASE + ny);
                
            }
        }

        return vis.size() > MAX;
    }
};
相关推荐
JAVA面经实录9174 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
开源Z5 小时前
LeetCode 42 · 接雨水:从暴力到双指针的三步优化
算法·leetcode
旖-旎6 小时前
《LeetCode 695 岛屿的最大面积 FloodFill DFS 解法》
c++·算法·力扣·深度优先遍历·floodfill
syagain_zsx6 小时前
STL 之 vector 讲练结合
c++·算法
MartinYeung58 小时前
[论文学习]DP2Unlearning:高效且具保证的大型语言模型遗忘框架(基于差分隐私的 LLM Unlearning 方法)
学习·算法·语言模型
Tian_Hang8 小时前
C++原型模式(Protype)
开发语言·c++·算法
bIo7lyA8v8 小时前
算法复杂度的渐进分析与实际运行时间的差异的技术8
算法
yuan199979 小时前
欧拉梁静力与屈曲计算的 MATLAB 实现(有限差分法 + 解析解)
开发语言·算法·matlab
汉克老师10 小时前
GESP7级C++考试语法知识(二、指数函数(3、综合练习)
c++·算法·数学建模·指数函数·gesp7级·复利