1036.逃离大迷宫

135 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

题目

1036.逃离大迷宫

题目大意

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

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

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

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

样例

img

数据规模

img

思路

假如不考虑xi,yi<106x_i,y_i<10^6这个条件,即xi,yix_i,y_i很小,考虑点source是否可以到达target,显然可以直接BFS搜索。

那现在加入条件xi,yi<106x_i,y_i<10^6,与此同时可以发现一个很重要的条件:0<=blocked.length<=2000<=blocked.length<=200,说明障碍点最多200个。障碍点连接起来可能有下述两种情况:

  • 10610610^6 * 10^6的矩阵分成两部分:包围圈内部和包围圈外部
  • 矩阵依旧只是单一的矩阵,无法进行分割。

但是考虑到障碍点很少,图很大这个条件。如果点source包围圈内并且以它作为起点出发进行bfs,会有多少个点被遍历?

  • 首先和矩阵边平行的障碍线肯定无法形出包围圈(点数不够)img
  • 障碍线2如下图: img
  • 障碍线3如下图 img

很显然第三种情况可以让包围圈内的点最多,最多有:n(n1)/2(n<=200)n*(n-1)/2(n<=200)个点。

那么就可以从点source出发,bfs最多遍历n(n1)/2n*(n-1)/2个点,一旦点数超过这个数量或者队列空了就终止。

  • 如果在bfs过程中遍历到了终点target,说明点source可以到达target;
  • bfs结束,遍历的点数小于等于n(n1)/2n*(n-1)/2说明点source在包围圈内;
  • bfs结束,遍历的点数大于n(n1)/2n*(n-1)/2说明点source在包围圈外;

然后再以点target为起点,点source为终点重复上述操作。

如果点source和点target都在圈内或者都在圈外说明两点是可达的,否则就是不可达。

代码

class Solution {
public:
    int dx[4]={1,-1,0,0};
    int dy[4]={0,0,1,-1};
    struct Node{
        int x,y;
    };
    map<long long,int>mp;
    map<long long,int>vis;
    int bfs(Node s,int n){
        // Node s=Node(source[0],source[1]);
        queue<Node>q;
        q.push(s);
        int cnt=0;
        while(!q.empty()&&cnt<=(n)*(n+1)/2){
            Node x=q.front();q.pop();
            long long a=x.x*1e6+x.y;
            if(vis[a])continue;
            vis[a]=1;
            cnt++;
            for(int i=0;i<4;i++){
                int nex_x=x.x+dx[i],nex_y=x.y+dy[i];
                long long w=nex_x*1e6+nex_y;
                if(nex_x>=0&&nex_x<1e6&&nex_y>=0&&nex_y<1e6&&!mp[w]){
                    Node nex;nex.x=nex_x;nex.y=nex_y;
                    q.push(nex);
                }
            }
        }
        if(cnt>(n)*(n-1)/2)return 1;
        return 0;
    }
    bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) {
        int n=blocked.size();
        for(auto it:blocked){
            long long now=it[0]*1e6+it[1];
            mp[now]=1;
        }
        Node s;s.x=source[0],s.y=source[1];
        int sign1=bfs(s,n);
        vis.clear();
        s.x=target[0],s.y=target[1];
        int sign2=bfs(s,n);
        if(sign1==sign2)return 1;
        return 0;
    }
};