📜  算法测验|须藤放置[1.7] |问题5(1)

📅  最后修改于: 2023-12-03 15:27:26.507000             🧑  作者: Mango

算法测验-须藤放置[1.7]-问题5

介绍

本题目是须藤放置游戏第1.7版问题5。该题目是一个算法测验,需要程序员利用所学算法解决问题。

游戏背景

须藤放置是一个益智类游戏,游戏中有一块由许多小正方形拼接而成的平面,并在平面上随机放置了许多正方形的小块。玩家需要在这个平面上摆放一些规定形状和大小的大块,使得这些大块恰好覆盖所有小块且不重叠。

问题描述

在这个游戏中,你需要解决以下问题:对于一个二维数组 $a$,其中每个元素都是 $0$ 或 $1$,若干个指定的 $1$ 所在的位置不能被大块完全覆盖,问最少需要添加几个额外的 $1$ 才能满足要求。

输入格式
  • 第$1$行:一个正整数 $n$,表示二维数组 $a$ 的行数。
  • 第$2$行:一个正整数 $m$,表示二维数组 $a$ 的列数。
  • 第$3$ ~ $(n+2)$行:每行 $m$ 个整数,表示数组 $a$。
  • 第$(n+3)$行:一个正整数 $k$,表示已知不能被大块完全覆盖的位置的个数。
  • 第$(n+4)$ ~ $(n+3+k)$行:每行两个正整数 $x,y$,分别表示一个位置不能被大块完全覆盖。
  • 数据保证满足$2\leq n,m,k\leq 1000$。
输出格式

一个整数,表示最少需要添加的额外的 $1$ 的数量。

示例

输入:

3
3
0 0 0
0 1 0
1 1 1
1
2 2

输出:

1
算法思路

首先使用深度优先搜索(DFS)将所有无法被大块覆盖的位置标记出来,可用一个二维数组 $vis$ 存储。而对于需要额外添加的 $1$,可以先将易被覆盖的位置全部涂黑色,再对剩余的未被标记的位置进行广度优先搜索(BFS)。因为横纵坐标坐标轴上存在环路,所以BFS时应该按照4个方向分别进行搜索。

代码实现
def dfs(x, y):
    if x in range(1, n + 1) and y in range(1, m + 1) and a[x - 1][y - 1] == 1 and not vis[x][y]:
        vis[x][y] = True
        dfs(x - 1, y)
        dfs(x + 1, y)
        dfs(x, y - 1)
        dfs(x, y + 1)
    else:
        return
    return

def bfs():
    ans = 0
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if a[i - 1][j - 1] == 0 and not vis[i][j]:
                flag = False
                queue = []
                queue.append([i, j])
                vis[i][j] = True
                while queue:
                    cur_x, cur_y = queue[0]
                    queue.pop(0)
                    if not (cur_x - 1 in range(1, n + 1) and a[cur_x - 2][cur_y - 1] == 0) and \
                            not (cur_x + 1 in range(1, n + 1) and a[cur_x][cur_y - 1] == 0) and \
                            not (cur_y - 1 in range(1, m + 1) and a[cur_x - 1][cur_y - 2] == 0) and \
                            not (cur_y + 1 in range(1, m + 1) and a[cur_x - 1][cur_y] == 0):
                        flag = True
                        break
                    if cur_x - 1 in range(1, n + 1) and not vis[cur_x - 1][cur_y] and a[cur_x - 2][cur_y - 1] == 0:
                        vis[cur_x - 1][cur_y] = True
                        queue.append([cur_x - 1, cur_y])
                    if cur_x + 1 in range(1, n + 1) and not vis[cur_x + 1][cur_y] and a[cur_x][cur_y - 1] == 0:
                        vis[cur_x + 1][cur_y] = True
                        queue.append([cur_x + 1, cur_y])
                    if cur_y - 1 in range(1, m + 1) and not vis[cur_x][cur_y - 1] and a[cur_x - 1][cur_y - 2] == 0:
                        vis[cur_x][cur_y - 1] = True
                        queue.append([cur_x, cur_y - 1])
                    if cur_y + 1 in range(1, m + 1) and not vis[cur_x][cur_y + 1] and a[cur_x - 1][cur_y] == 0:
                        vis[cur_x][cur_y + 1] = True
                        queue.append([cur_x, cur_y + 1])
                if flag:
                    ans += 1
    return ans


if __name__ == '__main__':
    n = int(input())
    m = int(input())
    a = []
    vis = [[False for j in range(m + 1)] for i in range(n + 1)]
    for i in range(n):
        row = input().split()
        row = [int(j) for j in row]
        a.append(row)
    k = int(input())
    for i in range(k):
        x, y = input().split()
        x = int(x)
        y = int(y)
        vis[x][y] = True
    for i in range(n):
        for j in range(m):
            if a[i][j] == 1 and not vis[i + 1][j + 1]:
                dfs(i + 1, j + 1)
    ans = bfs()
    print(ans)
总结

本题目主要考察程序员的算法解决问题的能力,在深度优先搜索和广度优先搜索等算法的应用过程中,程序员应对问题进行合理的抽象和建模,找出合适的数据结构和算法解决问题,不断地亲自高效地实践和汲取经验,方能成为真正的算法大师。