赞
踩
在一个 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。
0 <= blocked.length <= 200
很容易让人想到用dfs或bfs遍历所有格子,来确定能否到达终点,但此题的数据范围太大,10^6大概率会超时,所以需要另辟蹊径。
题目告诉我们blocked.length在[0,200] , 所以说大部分的位置都是空的,可以走的,那什么情况下无法赶往目标方格呢,就是入口或出口被分别包围起来了。
那我们只要证明,入口和出口没有被包围,就可以说明一定可以从源点走到目标点的。
那么怎么确认有没有被包围,就是我们要解决的问题了:
由题目可知,blocked的大小最多只有200个,而大迷宫是个10^6 * 10^6的超大迷宫,所以最大面积只能是它作为一条斜边依赖于两个墙角。
如果你不能理解,代码里的MAX也是可以设置为200 * 200(甚至是1e5),假设了超过blocked的个数一倍的大小。
之后,利用bfs的方式,分别判断入口和出口有没有被包围即可!
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; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。