📜  需要移除的最小子矩阵,使得剩余矩阵的总和可以被 K 整除(1)

📅  最后修改于: 2023-12-03 14:58:43.457000             🧑  作者: Mango

最小子矩阵的移除

在解决问题时,有时会需要移除矩阵中的一些元素以满足某些条件。本文将介绍如何在矩阵中移除最小的子矩阵,以使剩余矩阵的总和可以被 K 整除。

问题描述

给定一个 $n\times m$ 的矩阵$M$和一个整数$K$,请找出矩阵$M$中需要移除的最小子矩阵,使得剩余矩阵的总和可以被K整除。

解决方案

本问题可以使用动态规划来解决。下面介绍一种时间复杂度为 $O(n^3)$ 的动态规划解法。

状态定义

假设 $s_{i,j}$ 表示以 $(i,j)$ 为右下角的子矩阵的和,则状态转移方程为:

$s_{i,j} = M_{i,j} + s_{i-1,j} + s_{i,j-1} - s_{i-1,j-1}$

状态转移

接着定义一个新的状态 $r_{i,j}$,表示当从 $(1,1)$ 到 $(i,j)$ 的子矩阵的和被 $K$ 整除时,从 $(1,1)$ 到 $(i,j)$ 的最小子矩阵大小。

采用模运算,对于 $0 \leq i \leq n$ 和 $0 \leq j \leq m$,有:

$r_{i,j} = \min_{0\le x<i,0\le y<j}\left{ {\begin{aligned} r_{x,y} \quad if\ (M_{i,j} = 0) \ r_{x,y}+\left(i-x\right)\left(j-y\right) \quad else \end{aligned} }\right.$ (上面的公式渲染不了可以参照代码)

状态转移方程表示为:

$$r_{i,j}=\min{r_{i,j},r_{x,y}+(i-x)\times(j-y)}$$

其中 $x$ 和 $y$ 是所有满足 $s_{i,j}\equiv s_{x,y} \pmod K$ 的 $x$ 和 $y$ 中,使 $r_{x,y}$ 最小的那个。

初始状态

$r_{0,0}=0$。

最终结果

选取最后的一个 $r_{i,j}$,如果它等于 $\infty$,则无解,否则结果为 $r_{i,j}$。

代码实现(Python)
def remove_minimal_submatrix(M: List[List[int]], K: int) -> int:
    n, m = len(M), len(M[0])

    # 计算前缀和
    s = [[0] * (m+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            s[i][j] = M[i-1][j-1] + s[i-1][j] + s[i][j-1] - s[i-1][j-1]

    r = [[float('inf')] * (m+1) for _ in range(n+1)]
    r[0][0] = 0
    for i in range(1, n+1):
        for j in range(1, m+1):
            t = s[i][j]
            for x in range(i):
                for y in range(j):
                    if (t - s[x][j] - s[i][y] + s[x][y]) % K == 0:
                        r[i][j] = min(r[i][j], r[x][y] + (i-x) * (j-y))

    if r[n][m] == float('inf'):
        return -1
    else:
        return r[n][m]
时间复杂度

本算法的时间复杂度为 $O(n^3)$。