小R的蛋糕分享 | 豆包MarsCode AI刷题

54 阅读2分钟

问题描述

小R手里有一个大小为 n 行 m 列的矩形蛋糕,每个小正方形区域都有一个代表美味度的整数。小R打算切割出一个正方形的小蛋糕给自己,而剩下的部分将给小S。她希望两人吃的部分的美味度之和尽量接近。

我们定义小R吃到的部分的美味度之和为 s_1,而小S吃到的部分的美味度之和为 s_2,请你帮助小R找到一个切割方案,使得 |s_1 - s_2| 的值最小。

解题思路

  1. 前缀和矩阵:为了快速计算任意正方形区域的美味度之和,我们可以使用前缀和矩阵。前缀和矩阵 prefix_sum 的每个元素 prefix_sum[i][j] 表示从 (0, 0)(i, j) 的子矩阵的美味度之和。

  2. 遍历所有可能的正方形区域:我们需要遍历所有可能的正方形区域,计算每个正方形区域的美味度之和,并计算 |s_1 - s_2| 的值。

  3. 更新最小差值:在遍历过程中,不断更新最小的 |s_1 - s_2| 值。

代码人生

def solution(n: int, m: int, a: list) -> int:
    # 创建前缀和矩阵
    prefix_sum = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 计算前缀和矩阵
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            prefix_sum[i][j] = a[i-1][j-1] + prefix_sum[i-1][j] + prefix_sum[i][j-1] - prefix_sum[i-1][j-1]
    
    min_diff = float('inf')
    
    # 遍历所有可能的正方形区域
    for size in range(1, min(n, m) + 1):
        for i in range(size, n + 1):
            for j in range(size, m + 1):
                # 计算正方形区域的美味度之和
                s1 = prefix_sum[i][j] - prefix_sum[i-size][j] - prefix_sum[i][j-size] + prefix_sum[i-size][j-size]
                s2 = prefix_sum[n][m] - s1
                # 计算差值并更新最小差值
                min_diff = min(min_diff, abs(s1 - s2))
    
    return min_diff

关键步骤解释

  1. 前缀和矩阵的计算

    • prefix_sum[i][j] 表示从 (0, 0)(i, j) 的子矩阵的美味度之和。
    • 通过累加当前元素 a[i-1][j-1] 和减去重复计算的部分 prefix_sum[i-1][j-1] 来计算。
  2. 遍历所有可能的正方形区域

    • 对于每个可能的正方形大小 size,遍历所有可能的左上角坐标 (i, j)
    • 使用前缀和矩阵快速计算正方形区域的美味度之和 s1
  3. 计算差值并更新最小差值

    • 计算 s2 为整个矩阵的美味度之和减去 s1
    • 更新 min_diff 为当前差值和之前最小差值中的较小值。

测试样例

样例1:

输入:n = 3, m = 3, a = [[1, 2, 3], [2, 3, 4], [3, 2, 1]]
输出:1

样例2:

输入:n = 4, m = 4, a = [[1, 2, 3, 4], [4, 3, 2, 1], [1, 2, 3, 4], [4, 3, 2, 1]]
输出:2

样例3:

输入:n = 2, m = 2, a = [[5, 5], [5, 5]]
输出:10