列表

详情


2257. 统计网格图中没有被保卫的格子数

给你两个整数 m 和 n 表示一个下标从 0 开始的 m x n 网格图。同时给你两个二维整数数组 guards 和 walls ,其中 guards[i] = [rowi, coli] 且 walls[j] = [rowj, colj] ,分别表示第 i 个警卫和第 j 座墙所在的位置。

一个警卫能看到 4 个坐标轴方向(即东、南、西、北)的 所有 格子,除非他们被一座墙或者另外一个警卫 挡住 了视线。如果一个格子能被 至少 一个警卫看到,那么我们说这个格子被 保卫 了。

请你返回空格子中,有多少个格子是 没被保卫 的。

 

示例 1:

输入:m = 4, n = 6, guards = [[0,0],[1,1],[2,3]], walls = [[0,1],[2,2],[1,4]]
输出:7
解释:上图中,被保卫和没有被保卫的格子分别用红色和绿色表示。
总共有 7 个没有被保卫的格子,所以我们返回 7 。

示例 2:

输入:m = 3, n = 3, guards = [[1,1]], walls = [[0,1],[1,0],[2,1],[1,2]]
输出:4
解释:上图中,没有被保卫的格子用绿色表示。
总共有 4 个没有被保卫的格子,所以我们返回 4 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int countUnguarded(int m, int n, vector<vector<int>>& guards, vector<vector<int>>& walls) { } };

python3 解法, 执行用时: 1112 ms, 内存消耗: 48.7 MB, 提交时间: 2023-05-05 17:17:42

class Solution:
    def countUnguarded(self, m: int, n: int, guards: List[List[int]], walls: List[List[int]]) -> int:
        grid = [[0] * n for  _ in range(m)]   # 网格状态数组
        q = deque([])   # 广度优先搜索队列
        # 每个方向的单位向量
        dx = [1, 0, -1, 0]
        dy = [0, 1, 0, -1]
        for i, j in guards:
            grid[i][j] = -1
            for k in range(4):
                # 将四个方向视线对应的状态均添加进搜索队列中
                q.append((i, j, k))
        for i, j in walls:
            grid[i][j] = -2
        while q:
            x, y, k = q.popleft()
            nx, ny = x + dx[k], y + dy[k]
            if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] >= 0:
                # 沿着视线方向的下一个坐标合法,且不为警卫或墙
                if grid[nx][ny] & (1 << k) == 0:
                    # 对应状态未遍历过
                    grid[nx][ny] |= (1 << k)
                    q.append((nx, ny, k))
        res = 0   # 未被保护格子数目
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 0:
                    res += 1
        return res

golang 解法, 执行用时: 320 ms, 内存消耗: 15.3 MB, 提交时间: 2023-05-05 17:17:14

func countUnguarded(m, n int, guards, walls [][]int) (ans int) {
	// 构建网格
	a := make([][]int, m)
	for i := range a {
		a[i] = make([]int, n)
	}
	for _, p := range guards { a[p[0]][p[1]] = 1 }
	for _, p := range walls  { a[p[0]][p[1]] = 2 }

	// 按行模拟
	for _, row := range a {
		for j := 0; j < n; j++ {
			if row[j] == 2 { continue }
			st, has1 := j, false
			// 注意这里的 j 和外层循环的 j 是同一个变量
			for ; j < n && row[j] != 2; j++ {
				if row[j] == 1 {
					has1 = true
				}
			}
			if has1 {
				for ; st < j; st++ {
					if row[st] == 0 {
						row[st] = -1 // 能被保卫
					}
				}
			}
		}
	}

	// 按列模拟
	for j := 0; j < n; j++ {
		for i := 0; i < m; i++ {
			if a[i][j] == 2 { continue }
			st, has1 := i, false
			// 注意这里的 i 和外层循环的 i 是同一个变量
			for ; i < m && a[i][j] != 2; i++ {
				if a[i][j] == 1 {
					has1 = true
				}
			}
			if has1 {
				for ; st < i; st++ {
					if a[st][j] == 0 {
						a[st][j] = -1
					}
				}
			}
		}
	}

	// 统计答案
	for _, row := range a {
		for _, v := range row {
			if v == 0 {
				ans++
			}
		}
	}
	return
}

上一题