[leetcode] 5042. 逃离大迷宫

题目

在一个 10^6 x 10^6 的网格中,每个网格块的坐标为 (x, y),其中 0 <= x, y < 10^6

我们从源方格 source 开始出发,意图赶往目标方格 target。每次移动,我们都可以走到网格中在四个方向上相邻的方格,只要该方格不在给出的封锁列表 blocked 上。

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

 

示例 1:

输入:blocked = [[0,1],[1,0]], source = [0,0], target = [0,2]
输出:false
解释:
从源方格无法到达目标方格,因为我们无法在网格中移动。

示例 2:

输入:blocked = [], source = [0,0], target = [999999,999999]
输出:true
解释:
因为没有方格被封锁,所以一定可以到达目标方格。

 

提示:

  1. 0 <= blocked.length <= 200
  2. blocked[i].length == 2
  3. 0 <= blocked[i][j] < 10^6
  4. source.length == target.length == 2
  5. 0 <= source[i][j], target[i][j] < 10^6
  6. source != target

解题思路

是一道综合考察dfs、bfs、数据结构实现和算法实现的题。

首先,dfs不走最短路;bfs走最短路

其次,set是用红黑树实现的,引用primer里面一句话:”当只想知道一个值是否存在时,使用set容器是最合适的”

最后,bfs需要visit的record,不论是何种形式的 

这道题的基本思路是看能不能从source / target走出最多blocks.size()步(可以自己想一下),如果可以的话就是能够到达,不过其实只走了source就通过了。用set是为了把扫描的O(N)降低到O(logN)。

代码

class Solution {
public:
    bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) {
       queue<pair<pair<int, int>, int>> q;
        queue<pair<pair<int, int>, int>> q2;
        set<pair<int, int>> v;
        set<pair<int, int>> v2;
        set<pair<int, int>> b;
        
        for(auto p: blocked){
            pair<int, int> bp = make_pair(p[0], p[1]);
            b.insert(bp);
        }
 
        pair<int, int> s = make_pair(source[0], source[1]);
        pair<int, int> t = make_pair(target[0], target[1]);
        pair<pair<int, int>, int> src = make_pair(s, 0);
        pair<pair<int, int>, int> tg = make_pair(t, 0);
        
        q.push(src);
        int n = blocked.size();
        v.insert(s);
        bool flag = false;
        
        while(!q.empty()){
            pair<pair<int, int>, int> p = q.front();
            q.pop();
            int step = p.second;
            int r = p.first.first, c = p.first.second;
            
            if(step > n || (r == target[0] && c == target[1])){
                flag = true;
                break;
            }
 
            int row[] = {0, -1, 0, 1};
            int col[] = {1, 0, -1, 0};
            for(int i = 0; i < 4; i++){
                int nr = r + row[i], nc = c + col[i];
                if(nr < 0 || nc < 0 || nr >= 1000000 || nc >= 1000000){
                    continue;
                }
                pair<int, int> point = make_pair(nr, nc);
 
                if(b.find(point) == b.end() && v.find(point) == v.end()){
                    pair<pair<int, int>, int> np = make_pair(point, step + 1);
                    v.insert(point);
                    q.push(np);
                } 
            }
        }
        if(!flag){
            return false;
        }
        q2.push(tg);
        v2.insert(t);
        while(!q2.empty()){
            pair<pair<int, int>, int> p = q2.front();
            q2.pop();
            int step = p.second;
            int r = p.first.first, c = p.first.second;
            
            if(step > n || (r == source[0] && c == source[1])){
                return true;
            }
 
            int row[] = {0, -1, 0, 1};
            int col[] = {1, 0, -1, 0};
            for(int i = 0; i < 4; i++){
                int nr = r + row[i], nc = c + col[i];
                if(nr < 0 || nc < 0 || nr >= 1000000 || nc >= 1000000){
                    continue;
                }
                pair<int, int> point = make_pair(nr, nc);
 
                if(b.find(point) == b.end() && v2.find(point) == v2.end()){
                    pair<pair<int, int>, int> np = make_pair(point, step + 1);
                    v2.insert(point);
                    q2.push(np);
                } 
            }
        }
        return false;
    }
};

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值