【算法】逃离大迷宫

题目信息

在一个 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;
    }
};
相关推荐
启观川39 分钟前
数据结构与算法 -第 3 章 常用算法-动态规划
数据结构·笔记·python·算法
码爸42 分钟前
排序算法介绍
python·算法·排序算法
动词ing2 小时前
【题目练习】算法 组合总和||
算法
longlongzihan2 小时前
链表找环:Floyd 判圈算法(LeetCode 141 & 142 )
c++·算法·leetcode·链表
专业程序开发源2 小时前
flask家电故障预测系统92491-计算机课程设计/毕业设计
vscode·python·sql·算法·flask·课程设计
Logic1012 小时前
C语言/数据结构欧几里得算法题解:长方形切割最大正方形——贪心划分计数
c语言·数据结构·算法·贪心算法·时间复杂度·空间复杂度·欧几里得算法
yi0113 小时前
LeetCode 643. 子数组最大平均数 I|从暴力枚举到滑动窗口
人工智能·笔记·python·算法·leetcode·滑动窗口
极光通讯3 小时前
服务器内存来料检验(IQC)实操:批次追溯、外观判定与上机验证
java·服务器·算法
淡海水3 小时前
02-04-原理篇-GC Roots与对象图遍历
算法·unity·c#·图·gc·遍历·roots
ClickHouseDB4 小时前
ClickHouse 大规模 OpenTelemetry 数据接入架构的可靠性演进
算法