[leetcode]1036. 逃离大迷宫,双向广搜

题意很简单,就是在二维的表格中,有个起点坐标和终点坐标,还有不可达的多个坐标,问是否能够从起点到达终点。
单看这些信息的话,正常来说用深搜广搜都可以做,但问题出现在数据量上,题目给出的二维表范围是一个十万乘十万的表,用普通的搜索就绝对会超时,而这题的突破口,就是在不可达坐标的数量上。看提示信息有取值范围(下图),题目限定这种坐标blocker最多只有200个,而且题目也没有问最短路,而是问是否可达,那么怎么去利用这点呢?
取值范围

在二维表中,想要两点之间不互通,那就要封锁住所有的通路(废话),也就是说,两点被分到两个不同的连通块上,所以现在的问题就变成起点或终点是否被包围。
下面的代码使用的是广搜,普通的广搜结束条件就是队列为空或到达终点
思考blocker是否能截断起点和终点,可以再添加一条广搜的结束条件,那就是在广搜了k个位置后,队列还不为空的话,那就说明blocker以及最外围的边界不能拦截起点,但以它作为结束条件,广搜后的返回值的意义就不再是起点到终点可达 ,而是变成地图上的拦截点拦不住起点去终点。这就衍生一种可能,拦截点没能拦住起点往四周走动,但却包围了终点,让起点不可到达,所以这里要进行两种广搜,让终点也进行广搜去起点,只有两种广搜都返回true的话,才能说明起点终点相互连通。而因为限制了拦截点的数量,我这段代码的“k个位置”就设置为20000(但似乎能更小)
最后附上C++的代码:

class Solution {
public:
    int f[5]={0,1,0,-1,0};
    unordered_set<long long> block;
    long long maxNum = 1000000;
    int maxCnt = 20000;
    bool bfs(vector<int>& source, vector<int>& target){
        queue<pair<int,int>> q;
        q.push(pair<int,int>(source[0],source[1]));
        unordered_set<long long> flag;
        while(!q.empty()){
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for(int i = 0;i < 4; ++i){
                int nextX = x+f[i];
                int nextY = y+f[i+1];
                if(nextX >= 0 && nextX<maxNum && nextY >= 0 && nextY<maxNum){
                    long long k = (long long)nextX*maxNum+(long long)nextY;
                    if(flag.find(k)==flag.end() && block.find(k)==block.end()){
                        if(nextX == target[0] && nextY == target[1])return true;
                        q.push(pair<int,int>(nextX,nextY));
                        flag.insert(k);
                    }
                }
            }
            if(flag.size()>maxCnt)return true;
        }
        return false;
    }
    bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) {
        for(vector<int>& b:blocked){
            block.insert((long long)b[0]*maxNum+(long long)b[1]);
        }
        return bfs(source,target)&&bfs(target,source);
    }
};

其中q.push(pair<int,int>(nextX,nextY));可以换成q.emplace(X,Y);写的时候忘记了,不过也不会超时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值