题目描述:
在一个城市区域内,被划分成了n * m个连续的区块,每个区块都拥有不同的权值,代表着其土地价值。
目前,有两家开发公司,A 公司和 B 公司,希望购买这个城市区域的土地。
现在,需要将这个城市区域的所有区块分配给 A 公司和 B 公司。
然而,由于城市规划的限制,只允许将区域按横向或纵向划分成两个子区域,而且每个子区域都必须包含一个或多个区块。 为了确保公平竞争,你需要找到一种分配方式,使得 A 公司和 B 公司各自的子区域内的土地总价值之差最小。
注意:区块不可再分。
输入描述:
第一行输入两个正整数,代表 n 和 m。
接下来的 n 行,每行输出 m 个正整数。
输出描述:
请输出一个整数,代表两个子区域内土地总价值之间的最小差距。
示例
输入:
3 3
1 2 3
2 1 3
1 2 3
输出:
0
说明:
如果将区域按照如下方式划分:
1 2 | 3
2 1 | 3
1 2 | 3两个子区域内土地总价值之间的最小差距可以达到 0。
数据范围:
1 <= n, m <= 100;
n 和 m 不同时为 1。
解题思路:
1、明确题意:
矩阵只能划分一次,可以横向划分、纵向划分,需要计算两个子矩阵和,再计算子矩阵差值,并找到最小差值
2、使用矩阵前缀和数组:
创建一个(n + 1)*(m + 1)的前缀和矩阵。preSum[i][j] 表示以 (0, 0) 为左上角,(i, j) 为右下角的矩阵和。
二维矩阵前缀和preSum[i][j] = preSum[i][j - 1] + preSum[i - 1][j] +matrix[i][j] - preSum[i - 1][i - 1]
可以参考博文:
二维矩阵的前缀和+子矩阵的和-java_问题 i: 子矩阵求和【二维前缀和】-CSDN博客
3、遍历求子矩阵差值:
横向划分:上侧子矩阵和preSum[i][m];下侧子矩阵和preSum[n][m] - preSum[i][m]
纵向划分:左侧子矩阵和preSum[n][i];下侧子矩阵和preSum[n][m] - preSum[n][i]
计算并更新最小差值
代码部分:
def minDifferece(n, m, matrix):
# 前缀和, preSum[i][j] 表示i行j列子矩阵和
preSum = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(1, n + 1): # 行
for j in range(1, m + 1): # 列
preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] + matrix[i - 1][j - 1] - preSum[i - 1][j - 1]
min_diff = float('inf')
# 横向分割
for i in range(1, n):
top_sum = preSum[i][m] # 前i行矩阵和
bottom_sum = preSum[n][m] - top_sum # 后n - 前i行矩阵和
min_diff = min(min_diff, abs(top_sum - bottom_sum)) # 计算土地最小差值
# 纵向分割
for j in range(1, m):
left_sum = preSum[n][j] # 前j列矩阵和
right_sum = preSum[n][m] - left_sum # 后m - j 前j列矩阵和
min_diff = min(min_diff, abs(left_sum - right_sum))
return min_diff
if __name__ == '__main__':
n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]
result = minDifferece(n, m, matrix)
print(result)
知识点:二维数组、前缀和
结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路