leetcode1036 逃离大迷宫(bfs 坐标hash处理)
链接:https://leetcode-cn.com/problems/escape-a-large-maze/
题目
在一个 106 x 106 的网格中,每个网格上方格的坐标为 (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 < 106
source != target
题目数据保证 source 和 target 不在封锁列表内
思路
由于网格数量为106*106,所以直接dfs或者bfs都会超时
但是blocked封锁点数量最多只有200个,也就是说source点以及target点附近能走的点数大于blocked能封锁的最大面积点数 或者在能走的范围内直接搜到对方,即为可以达到
blocked的最大封锁面积 如图即为和边界围成三角的情况,封锁面积为(n-1)*n/2,所以问题转化为 对source点 和target点bfs搜索 判断可行路径大于最大封锁点的问题
坐标hash构造可以由两种:
- 使用一个素数作为底,比如13331 ,131等 x*base+y作为hash值
- 使用大数二进制存储 因为是106*106,220-1大于106,所以可以用大数二进制来存坐标 ,取其中40位 前20位存x,后20位存y 即(x<<20+y)
class Solution {
public:
static constexpr int dir[4][2]={{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
long long BASE=13331 ;
int MAX=1e5;
static constexpr int edge=1e6;
unordered_set<long long>st;
bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) {
for(auto &b:blocked){
st.insert(b[0]*BASE +b[1]);
}
int n=blocked.size();
MAX=(n-1)*n/2;
return check(source,target)&check(target,source);
}
bool check(vector<int >&a,vector<int>&b){
unordered_set<long long>vis;
queue<pair<int,int>>q;
q.push({a[0],a[1]});
vis.insert(a[0]*BASE+a[1]);
while(q.size() &&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;
for(int i=0;i<4;i++){
int nx=x+dir[i][0],ny=y+dir[i][1];
if(nx<0||nx>edge-1||ny<0||ny>edge-1)continue;
if(st.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;// 注意判断的是走过路径的数量
}
};