开发商购买土地

题目描述:

在一个城市区域内,被划分成了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)

知识点:二维数组、前缀和


结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值