小M的蛋糕切割问题 | 豆包MarsCode AI 刷题

140 阅读3分钟

问题描述

小M有一个 𝑛×𝑚的矩形蛋糕,蛋糕被分为 𝑛×𝑚 个区域,每个区域都有一个美味度。她希望通过一刀将蛋糕切成两部分,一部分自己吃,另一部分给小团。切下的区域必须是完整的,即不能把某个小正方形切成两个小区域。

小M希望两个人吃的部分的美味度之和尽量接近。你的任务是计算出美味度差的最小值,即 ∣𝑠1−𝑠2∣ 的最小值,其中 𝑠1 是小M吃到的美味度,𝑠2 是小团吃到的美味度。

测试样例

样例1:

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

样例2:

输入:n = 3, m = 3, a = [[3, 2, 1], [4, 5, 6], [7, 8, 9]]
输出:3

样例3:

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

解题思路

  • 题目要求:

    • 给定一个𝑛×𝑚的蛋糕,每个区域的美味度已知。
    • 通过一次切割将蛋糕分成两部分,每部分必须包含完整的小块。
    • 计算并返回两部分美味度差的最小值。
  • 分析:

    • 根据题目条件,蛋糕的切割方式仅限于水平切割和垂直切割,不考虑斜切。
    • 水平切割: 对于每一行,计算从左上角到当前行的累积美味度,以及从右下角到当前行的累积美味度,然后计算这两部分的差值,并更新最小差异。
    • 垂直切割: 对于每一列,计算从左上角到当前列的累积美味度,以及从右下角到当前列的累积美味度,然后计算这两部分的差值,并更新最小差异。

代码实现

def solution(n: int, m: int, a: list) -> int:
    # 计算总和
    total_sum = sum(sum(row) for row in a)
    
    # 初始化累积和数组
    sums = [[0] * (m + 1) for _ in range(n + 1)]
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            sums[i][j] = sums[i-1][j] + sums[i][j-1] - sums[i-1][j-1] + a[i-1][j-1]
    
    # 寻找最小差异
    min_diff = float('inf')
    
    # 水平切割
    for i in range(1, n + 1):
        left_sum = sums[i][m]  # 左侧部分的和
        right_sum = total_sum - left_sum  # 右侧部分的和
        min_diff = min(min_diff, abs(left_sum - right_sum))
    
    # 垂直切割
    for j in range(1, m + 1):
        top_sum = sums[n][j]  # 上部分的和
        bottom_sum = total_sum - top_sum  # 下部分的和
        min_diff = min(min_diff, abs(top_sum - bottom_sum))
    
    return min_diff

if __name__ == '__main__':
    print(solution(2, 3, [[1, 1, 4], [5, 1, 4]]) == 0)
    print(solution(3, 3, [[3, 2, 1], [4, 5, 6], [7, 8, 9]]) == 3)
    print(solution(2, 2, [[1, 2], [3, 4]]) == 2)

总结

这段代码实现了一个算法,用于解决小M的蛋糕切割问题。它首先计算整个蛋糕的美味度总和,然后通过构建一个累积和数组来快速获取任意区域的美味度总和。接着,算法遍历所有可能的水平和垂直切割线,对于每种切割方式,计算两部分的美味度之和,并更新最小美味度差。最终,算法返回最小的美味度差值,确保小M和小团得到的蛋糕部分美味度尽可能接近。这个过程考虑了所有可能的切割方式,以找到使美味度差最小的最优解。