Skip to content

Latest commit

 

History

History
408 lines (353 loc) · 12.4 KB

File metadata and controls

408 lines (353 loc) · 12.4 KB

English Version

题目描述

给你一个下标从 0 开始大小为 m x n 的二维整数数组 grid ,它表示一个网格图。每个格子为下面 3 个值之一:

  • 0 表示草地。
  • 1 表示着火的格子。
  • 2 表示一座墙,你跟火都不能通过这个格子。

一开始你在最左上角的格子 (0, 0) ,你想要到达最右下角的安全屋格子 (m - 1, n - 1) 。每一分钟,你可以移动到 相邻 的草地格子。每次你移动 之后 ,着火的格子会扩散到所有不是墙的 相邻 格子。

请你返回你在初始位置可以停留的 最多 分钟数,且停留完这段时间后你还能安全到达安全屋。如果无法实现,请你返回 -1 。如果不管你在初始位置停留多久,你 总是 能到达安全屋,请你返回 109 。

注意,如果你到达安全屋后,火马上到了安全屋,这视为你能够安全到达安全屋。

如果两个格子有共同边,那么它们为 相邻 格子。

 

示例 1:

输入:grid = [[0,2,0,0,0,0,0],[0,0,0,2,2,1,0],[0,2,0,0,1,2,0],[0,0,2,2,2,0,2],[0,0,0,0,0,0,0]]
输出:3
解释:上图展示了你在初始位置停留 3 分钟后的情形。
你仍然可以安全到达安全屋。
停留超过 3 分钟会让你无法安全到达安全屋。

示例 2:

输入:grid = [[0,0,0,0],[0,1,2,0],[0,2,0,0]]
输出:-1
解释:上图展示了你马上开始朝安全屋移动的情形。
火会蔓延到你可以移动的所有格子,所以无法安全到达安全屋。
所以返回 -1 。

示例 3:

输入:grid = [[0,0,0],[2,2,0],[1,2,0]]
输出:1000000000
解释:上图展示了初始网格图。
注意,由于火被墙围了起来,所以无论如何你都能安全到达安全屋。
所以返回 109

 

提示:

  • m == grid.length
  • n == grid[i].length
  • 2 <= m, n <= 300
  • 4 <= m * n <= 2 * 104
  • grid[i][j] 是 0 ,1 或者 2 。
  • grid[0][0] == grid[m - 1][n - 1] == 0

解法

方法一:二分查找 + BFS

二分枚举停留时间 t,找到满足条件的最大 t。

Python3

class Solution:
    def maximumMinutes(self, grid: List[List[int]]) -> int:
        def spread(fire, q):
            nf = deque()
            while q:
                i, j = q.popleft()
                for a, b in [[0, -1], [0, 1], [-1, 0], [1, 0]]:
                    x, y = i + a, j + b
                    if 0 <= x < m and 0 <= y < n and not fire[x][y] and grid[x][y] == 0:
                        fire[x][y] = True
                        nf.append((x, y))
            return nf

        def check(t):
            fire = [[False] * n for _ in range(m)]
            f = deque()
            for i, row in enumerate(grid):
                for j, v in enumerate(row):
                    if v == 1:
                        fire[i][j] = True
                        f.append((i, j))
            while t and f:
                f = spread(fire, f)
                t -= 1
            if fire[0][0]:
                return False
            q = deque([(0, 0)])
            vis = [[False] * n for _ in range(m)]
            vis[0][0] = True
            while q:
                for _ in range(len(q)):
                    i, j = q.popleft()
                    if fire[i][j]:
                        continue
                    for a, b in [[0, -1], [0, 1], [-1, 0], [1, 0]]:
                        x, y = i + a, j + b
                        if (
                            0 <= x < m
                            and 0 <= y < n
                            and not fire[x][y]
                            and not vis[x][y]
                            and grid[x][y] == 0
                        ):
                            if x == m - 1 and y == n - 1:
                                return True
                            vis[x][y] = True
                            q.append((x, y))
                f = spread(fire, f)
            return False

        m, n = len(grid), len(grid[0])
        left, right = -1, m * n
        while left < right:
            mid = (left + right + 1) >> 1
            if check(mid):
                left = mid
            else:
                right = mid - 1
        return int(1e9) if left == m * n else left

Java

class Solution {
    private static int[] dirs = {-1, 0, 1, 0, -1};
    private int[][] grid;
    private int m;
    private int n;

    public int maximumMinutes(int[][] grid) {
        this.grid = grid;
        m = grid.length;
        n = grid[0].length;
        int left = -1, right = m * n;
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if (check(mid)) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return left == m * n ? (int) 1e9 : left;
    }

    private boolean check(int t) {
        boolean[][] fire = new boolean[m][n];
        Deque<int[]> f = new ArrayDeque<>();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1) {
                    fire[i][j] = true;
                    f.offer(new int[] {i, j});
                }
            }
        }
        while (t-- > 0 && !f.isEmpty()) {
            f = spread(fire, f);
        }
        if (fire[0][0]) {
            return false;
        }
        Deque<int[]> q = new ArrayDeque<>();
        boolean[][] vis = new boolean[m][n];
        q.offer(new int[] {0, 0});
        vis[0][0] = true;
        while (!q.isEmpty()) {
            for (int i = q.size(); i > 0; --i) {
                int[] p = q.poll();
                if (fire[p[0]][p[1]]) {
                    continue;
                }
                for (int k = 0; k < 4; ++k) {
                    int x = p[0] + dirs[k], y = p[1] + dirs[k + 1];
                    if (x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && !vis[x][y]
                        && grid[x][y] == 0) {
                        if (x == m - 1 && y == n - 1) {
                            return true;
                        }
                        vis[x][y] = true;
                        q.offer(new int[] {x, y});
                    }
                }
            }
            f = spread(fire, f);
        }
        return false;
    }

    private Deque<int[]> spread(boolean[][] fire, Deque<int[]> q) {
        Deque<int[]> nf = new ArrayDeque<>();
        while (!q.isEmpty()) {
            int[] p = q.poll();
            for (int k = 0; k < 4; ++k) {
                int x = p[0] + dirs[k], y = p[1] + dirs[k + 1];
                if (x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && grid[x][y] == 0) {
                    fire[x][y] = true;
                    nf.offer(new int[] {x, y});
                }
            }
        }
        return nf;
    }
}

C++

class Solution {
public:
    vector<int> dirs = {-1, 0, 1, 0, -1};

    int maximumMinutes(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        int left = -1, right = m * n;
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if (check(mid, grid))
                left = mid;
            else
                right = mid - 1;
        }
        return left == m * n ? 1e9 : left;
    }

    bool check(int t, vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<bool>> fire(m, vector<bool>(n));
        queue<vector<int>> f;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == 1) {
                    fire[i][j] = true;
                    f.push({i, j});
                }
            }
        }
        while (t-- && f.size()) f = spread(fire, f, grid);
        queue<vector<int>> q;
        vector<vector<bool>> vis(m, vector<bool>(n));
        q.push({0, 0});
        vis[0][0] = true;
        while (!q.empty()) {
            for (int i = q.size(); i > 0; --i) {
                auto p = q.front();
                q.pop();
                if (fire[p[0]][p[1]]) continue;
                for (int k = 0; k < 4; ++k) {
                    int x = p[0] + dirs[k], y = p[1] + dirs[k + 1];
                    if (x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && !vis[x][y] && grid[x][y] == 0) {
                        if (x == m - 1 && y == n - 1) return true;
                        vis[x][y] = true;
                        q.push({x, y});
                    }
                }
            }
            f = spread(fire, f, grid);
        }
        return false;
    }

    queue<vector<int>> spread(vector<vector<bool>>& fire, queue<vector<int>>& f, vector<vector<int>>& grid) {
        queue<vector<int>> nf;
        int m = grid.size(), n = grid[0].size();
        while (!f.empty()) {
            auto p = f.front();
            f.pop();
            for (int k = 0; k < 4; ++k) {
                int x = p[0] + dirs[k], y = p[1] + dirs[k + 1];
                if (x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && grid[x][y] == 0) {
                    fire[x][y] = true;
                    nf.push({x, y});
                }
            }
        }
        return nf;
    }
};

Go

func maximumMinutes(grid [][]int) int {
	m, n := len(grid), len(grid[0])
	dirs := []int{-1, 0, 1, 0, -1}

	spread := func(fire [][]bool, q [][]int) [][]int {
		nf := [][]int{}
		for len(q) > 0 {
			p := q[0]
			q = q[1:]
			for k := 0; k < 4; k++ {
				x, y := p[0]+dirs[k], p[1]+dirs[k+1]
				if x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && grid[x][y] == 0 {
					fire[x][y] = true
					nf = append(nf, []int{x, y})
				}
			}
		}
		return nf
	}

	check := func(t int) bool {
		fire := make([][]bool, m)
		vis := make([][]bool, m)
		f := [][]int{}
		for i, row := range grid {
			fire[i] = make([]bool, n)
			vis[i] = make([]bool, n)
			for j, v := range row {
				if v == 1 {
					fire[i][j] = true
					f = append(f, []int{i, j})
				}
			}
		}
		for t > 0 && len(f) > 0 {
			f = spread(fire, f)
			t--
		}
		if fire[0][0] {
			return false
		}
		q := [][]int{{0, 0}}
		vis[0][0] = true
		for len(q) > 0 {
			for i := len(q); i > 0; i-- {
				p := q[0]
				q = q[1:]
				if fire[p[0]][p[1]] {
					continue
				}
				for k := 0; k < 4; k++ {
					x, y := p[0]+dirs[k], p[1]+dirs[k+1]
					if x >= 0 && x < m && y >= 0 && y < n && !fire[x][y] && !vis[x][y] && grid[x][y] == 0 {
						if x == m-1 && y == n-1 {
							return true
						}
						vis[x][y] = true
						q = append(q, []int{x, y})
					}
				}
			}
			f = spread(fire, f)
		}
		return false
	}

	left, right := -1, m*n
	for left < right {
		mid := (left + right + 1) >> 1
		if check(mid) {
			left = mid
		} else {
			right = mid - 1
		}
	}
	if left == m*n {
		return int(1e9)
	}
	return left
}

TypeScript

...