📌  相关文章
📜  最小化在给定矩阵中所有对均具有按位与的数组的总和(1)

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

最小化矩阵中所有对均具有按位与的数组的总和

在给定一个 n x m 的矩阵 matrix 中,每一对相邻元素都有一种按位与的操作方法,即将它们的每一个对应位进行“与”运算,构成一个新的数组。现在你需要找到一种操作方案,使得对于矩阵中的每一对相邻元素,通过该操作得到的数组的总和最小。

例如,在矩阵 [[1,3],[3,5]] 中,存在以下 4 组相邻元素:

[[1,3],[3,5]] 中,1 和 3 进行按位与操作得到 1,3 和 5 进行按位与操作得到 1,这两个数组的总和为 2。 [[3,5],[1,3]] 中,3 和 5 进行按位与操作得到 1,1 和 3 进行按位与操作得到 1,这两个数组的总和为 2。 [[1,3],[3,5]] 中,3 和 1 进行按位与操作得到 1,5 和 3 进行按位与操作得到 1,这两个数组的总和为 2。 [[3,5],[1,3]] 中,5 和 3 进行按位与操作得到 1,3 和 1 进行按位与操作得到 1,这两个数组的总和为 2。 因此,对于矩阵 [[1,3],[3,5]],最小的结果为 2。

思路

对于每一位,我们只需要考虑该位置在所有数中是否为 1,如果不是,则统计该位置为 1 的数的个数,在所有满足该位置为 1 的数中选取两个数进行按位与运算,这样就可以得到该位置上的贡献。

具体地,我们可以枚举每一位,统计该位置为 1 的数的个数 cnt,如果 cnt 大于等于 2,则该位的贡献就是 (cnt * (cnt - 1)) // 2,否则该位的贡献为 0。所有位的贡献之和就是最终结果。

代码
class Solution:
    def matrixScore(self, matrix: List[List[int]]) -> int:
        n, m = len(matrix), len(matrix[0])
        res = n * (1 << (m - 1))

        for j in range(1, m):
            cnt = 0
            for i in range(n):
                if matrix[i][j] == matrix[i][0]:
                    cnt += 1
            res += max(cnt, n - cnt) * (1 << (m - 1 - j))

        return res

其中,我们通过枚举每一列,判断该列中 1 的数量是否大于该列中 0 的数量,如果是则该列不需要被翻转,否则需要翻转该列。最终的结果就是所有行均翻转后的矩阵中的得分。