问题描述
小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和小团得到的蛋糕部分美味度尽可能接近。这个过程考虑了所有可能的切割方式,以找到使美味度差最小的最优解。