📜  门| GATE-CS-2017(套装2)|第 38 题(1)

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

门| GATE-CS-2017(套装2)|第 38 题
题目描述

给定一个M x N的0/1矩阵A,可以执行以下操作:

  • 行反转:将矩阵的一行翻转,即0变为1,1变为0。
  • 列反转:将矩阵的一列翻转,即0变为1,1变为0。

要求:计算使用上述操作,使矩阵的每一行均相等所需的最小操作次数。若不能通过操作使得每一行相等,则返回-1。

输入格式
  • 第1行:包含两个正整数M和N,表示矩阵A的尺寸
  • 第2~M + 1行:每行包含N个整数,表示矩阵的一行。
输出格式
  • 一个整数:表示使矩阵的每一行均相等所需的最小操作次数。如果无法通过操作使得每一行相等,则返回-1。
示例

输入:

3 3
1 0 0
1 0 0
1 1 1

输出:

1
解题思路
  • 我们可以枚举行中的数为0或者1,来判断是不是一个合法的答案。
  • 对于所有的行,第一个元素必须相等。否则,如果通过操作使第一个元素相等,那么其他行也依然不相等,使得最小操作次数不升。如果第一个元素都不相等,那么就更加不可能通过操作使所有行相等了。
  • 对于任意一个操作序列(行反转和列反转操作),如果A和B的最终结果相同,则对于任何一个中间状态(部分变换的结果),A和B的结果也是相同的。因此,我们可以始终固定矩阵中的第一列,使其全部为0,然后对于每一行,只能通过行反转来将其变成满足第一列的要求(第一列为0)的序列。
  • 我们枚举第一行、第二行、等等,如果最终使得每一行均相等,那么一定存在一个中间的1xm 的操作矩阵,使得该操作矩阵作用于A上,得到的矩阵B满足B的每一行仅和A的第一行不同。
  • 计算答案:如果矩阵中的每一行均相等,则答案为0。否则,我们枚举行中的数为0或者1,假设行中数为1的个数为c,则答案为min(c,n - c)。
参考代码

python 代码如下:

def minOps(arr):
    n, m = len(arr), len(arr[0])
    if n == 0 or m == 0:
        return 0

    # 核心操作:枚举第一行,得到序列后判断
    seq = [arr[0][j] ^ arr[i][j] for j in range(m)]
    # 如果B的每一行仅和A的第一行不同,则假设第i个数为1,统计c。
    c = 0
    for i in range(1, n):
        cur = [arr[0][j] ^ arr[i][j] for j in range(m)]
        if cur != seq:
            cur = [1 - cur[j] for j in range(m)]
            if cur != seq:
                return -1
            c += 1
        else:
            c += 1

    return min(c, m - c)

arr = [[1, 0, 0], [1, 0, 0], [1, 1, 1]]
print(minOps(arr)) # 1