在一个 106 x 106 的网格中,每个网格上方格的坐标为 (x, y) 。
现在从源方格 source = [sx, sy] 开始出发,意图赶往目标方格 target = [tx, ty] 。数组 blocked 是封锁的方格列表,其中每个 blocked[i] = [xi, yi] 表示坐标为 (xi, yi) 的方格是禁止通行的。
每次移动,都可以走到网格中在四个方向上相邻的方格,只要该方格 不 在给出的封锁列表 blocked 上。同时,不允许走出网格。
只有在可以通过一系列的移动从源方格 source 到达目标方格 target 时才返回 true。否则,返回 false。
代码如下:
class Solution {
Set<Long> forbid=new HashSet<>();
long max=(long)1e6;
long from;
long to;
public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
from=max*(long)source[0]+(long)source[1];
to=max*(long)target[0]+(long)target[1];
for(int i=0;i<blocked.length;i++){forbid.add(max*(long)blocked[i][0]+(long)blocked[i][1]);}
Set<Long> start=new HashSet<>();
Set<Long> end=new HashSet<>();
int maxSize=blocked.length*(blocked.length-1)/2;
findPath(target[0],target[1],maxSize,end);
findPath(source[0],source[1],maxSize,start);
return start.size()>maxSize&&end.size()>maxSize||end.contains(from)||start.contains(to);
}
public void findPath(int i,int j,int maxSize,Set<Long> set){
long p=max*(long)i+(long)j;
if(forbid.contains(p)||set.contains(p)||i<0||j<0||i==max||j==max){return;}
set.add(p);
if(set.size()>maxSize||set.contains(to)&&set.contains(from)){return;}
findPath(i+1,j,maxSize,set);
findPath(i-1,j,maxSize,set);
findPath(i,j+1,maxSize,set);
findPath(i,j-1,maxSize,set);
}
}
离散化压缩点的坐标,可以大大提高搜索的效率,而且只需要从一个点开始就可以了,不过需要注意的是,每个block点四周的坐标也需要加入离散的map,目的是在保证点的相对位置的同时,使得坐标值本不相邻的点在离散后也是不相邻的
class Solution {
boolean cameBefore[][]=new boolean[650][650];
int r=0;
int k=0;
public boolean isEscapePossible(int[][] blocked, int[] source, int[] target) {
int max=(int)1e6;
TreeSet<Integer> row=new TreeSet<>();
TreeSet<Integer> col=new TreeSet<>();
row.add(source[0]);
row.add(target[0]);
col.add(source[1]);
col.add(target[1]);
for(int i=0;i<blocked.length;i++){
row.add(blocked[i][0]);
if(blocked[i][0]>0){row.add(blocked[i][0]-1);}
if(blocked[i][0]<max-1){row.add(blocked[i][0]+1);}
col.add(blocked[i][1]);
if(blocked[i][1]>0){col.add(blocked[i][1]-1);}
if(blocked[i][1]<max-1){col.add(blocked[i][1]+1);}
}
Map<Integer,Integer> map1=new HashMap<>();//行映射
Map<Integer,Integer> map2=new HashMap<>();//列映射
for(int a:row){
map1.put(a,r);
r++;
}
for(int a:col){
map2.put(a,k);
k++;
}
for(int i=0;i<blocked.length;i++){cameBefore[map1.get(blocked[i][0])][map2.get(blocked[i][1])]=true;}
findPath(map1.get(source[0]),map2.get(source[1]));
return cameBefore[map1.get(target[0])][map2.get(target[1])];
}
public void findPath(int x,int y){
if(x<0||y<0||x==r||y==k||cameBefore[x][y]){return;}
cameBefore[x][y]=true;
findPath(x+1,y);
findPath(x-1,y);
findPath(x,y+1);
findPath(x,y-1);
}
}