2022-04-16:在一个10^6 * 10^6的网格中, source = [sx, sy]是出发位置,target = [tx, ty]是目标位置, 数组blocked是封锁的方格列表,被禁止的方格数量不超过200, blocked[i] = [xi, yi] 表示(xi, yi)的方格是禁止通行的, 每次移动都可以走上、下、左、右四个方向, 但是来到的位置不能在封锁列表blocked上, 同时不允许走出网格。 如果从source能到达target返回 true。否则返回false。

答案2022-04-16:

宽度优先遍历。 n个×,围住n*(n-1)/2个格子。

代码用rust编写。代码如下:

use std::collections::HashSet;

fn main() {
    let blocked: Vec<Vec<isize>> = vec![vec![0, 1], vec![1, 0]];
    let source: Vec<isize> = vec![0, 0];
    let target: Vec<isize> = vec![0, 2];
    let ret: bool = isEscapePossible(blocked, source, target);
    println!("{}", ret);
}

const offset: isize = 1000000;

fn isEscapePossible(blocked: Vec<Vec<isize>>, source: Vec<isize>, target: Vec<isize>) -> bool {
    let n = blocked.len();
    let maxPoints: isize = (n * (n - 1) / 2) as isize;
    let mut blockSet: HashSet<isize> = vec![].into_iter().collect();
    for i in 0..n {
        blockSet.insert(blocked[i][0] * offset + blocked[i][1]);
    }
    return bfs(
        source[0], source[1], target[0], target[1], maxPoints, &blockSet,
    ) && bfs(
        target[0], target[1], source[0], source[1], maxPoints, &blockSet,
    );
}

fn bfs(
    fromX: isize,
    fromY: isize,
    toX: isize,
    toY: isize,
    maxPoints: isize,
    blockSet: &HashSet<isize>,
) -> bool {
    let mut visited: HashSet<isize> = vec![].into_iter().collect();
    let mut queue: Vec<isize> = Vec::new();
    visited.insert(fromX * offset + fromY);
    queue.push(fromX * offset + fromY);
    while queue.len() > 0 && (visited.len() as isize <= maxPoints) {
        let cur = queue[0];
        queue.remove(0);
        let curX = cur / offset;
        let curY = cur - curX * offset;
        if (findAndAdd(curX - 1, curY, toX, toY, blockSet, &mut visited, &mut queue)
            || findAndAdd(curX + 1, curY, toX, toY, blockSet, &mut visited, &mut queue)
            || findAndAdd(curX, curY - 1, toX, toY, blockSet, &mut visited, &mut queue)
            || findAndAdd(curX, curY + 1, toX, toY, blockSet, &mut visited, &mut queue))
        {
            return true;
        }
    }
    return visited.len() as isize > maxPoints;
}

// 来到的点,(row, col)
// 要寻找的目标点,toX, toY
// HashSet<Long> blockSet存着不能走的格子!障碍点!
// HashSet<Long> visited, Queue<Long> queue 为了宽度优先遍历服务的!
// visited,已经处理过的点,请不要重复的放入queue
// 如果已经到达了(toX, toY)
fn findAndAdd(
    row: isize,
    col: isize,
    toX: isize,
    toY: isize,
    blockSet: &HashSet<isize>,
    visited: &mut HashSet<isize>,
    queue: &mut Vec<isize>,
) -> bool {
    if (row < 0 || row == offset || col < 0 || col == offset) {
        return false;
    }
    if (row == toX && col == toY) {
        return true;
    }
    let value = row * offset + col;
    if !blockSet.contains(&value) && !visited.contains(&value) {
        visited.insert(value);
        queue.push(value);
    }
    return false;
}

执行结果如下:

在这里插入图片描述


左神java代码