📌  相关文章
📜  门| Sudo GATE 2020 Mock I(2019 年 12 月 27 日)|第 46 题(1)

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

题目描述

给定一个 n x m 的矩阵,其中每个元素都是 0 或 1。你要用翻转的方式,将整个矩阵变成全零矩阵。对于一个 0-1 矩阵,每次可以将任意一个元素取反。

函数签名
def change_matrix(matrix: List[List[int]]) -> int:
    pass
输入
  • matrix: 一个二维的数组,表示要操作的矩阵。其中 matrix[i][j] 表示矩阵中第 i + 1 行,第 j + 1 列的元素。保证 n, m <= 100
输出
  • 返回一个整数,表示操作所需的最少次数。
示例
assert change_matrix([[1,1],[1,0]]) == 3
assert change_matrix([[1,0,0],[1,0,1]]) == 6
assert change_matrix([[1,0,0,1,1],[0,0,1,0,1]]) == 10
思路

将矩阵中每个不为 0 的元素都作为一个点。可以将每个点看作一个开关,状态只有 2 种:开或关。开关状态之间相互影响,通过经典的异或运算来模拟这种影响。

具体地,从左到右第 $i$ 个点的状态为:

  • $A[i][1]\oplus A[i-1][2]\oplus A[i][2]\oplus A[i+1][2]$,若 $i=1$,则 $A[i-1]$ 为 0
  • $A[i][2]\oplus A[i-1][1]\oplus A[i][1]\oplus A[i+1][1]$,若 $i=m$,则 $A[i+1]$ 为 0

若可以通过合法的操作将某一列全部变为 0,则这一列整体视为关,如此迭代下去,直到所有点都关。

代码实现
from typing import List

def change_matrix(matrix: List[List[int]]) -> int:
    n, m = len(matrix), len(matrix[0])
    A = [[0] * (m+1) for _ in range(n+1)]
    for i in range(n):
        for j in range(m):
            A[i+1][j+1] = matrix[i][j]
    
    def press(A, x, y):
        A[x][y] ^= 1
        A[x-1][y] ^= 1
        A[x+1][y] ^= 1
        A[x][y-1] ^= 1
        A[x][y+1] ^= 1
        
    def work(A):
        ans = 0
        res = True
        while res:
            res = False
            B = [[A[i][j] for j in range(m+1)] for i in range(n+1)]
            for i in range(1, n+1):
                for j in range(1, m+1):
                    if B[i-1][j] ^ B[i][j-1] ^ B[i][j] ^ B[i][j+1] ^ B[i+1][j]:
                        press(A, i, j)
                        res = True
                        ans += 1
        return ans

    return work(A)