44. 开发商购买土地

44. 开发商购买土地

前缀和

思路
可能的情况有两类,A占前 i 行,B占剩余行;A占前 j 列,B占剩余列。
若直接暴力枚举,第一层 for 循环遍历行(控制行的切分),第二层、第三层 for 循环计算A区域中元素和,时间复杂度O(n^3)。
1、计算每行的和,得到行前缀和数组horizontoal,horizontoal[i]表示第i行元素和,
计算每列的和,得到列前缀和数组vertical,vertical[j]表示第j行元素和。
2、枚举按行切分的情况,计算差值,
枚举按列切分的情况,计算差值。
时间复杂度O(n^2)

import java.util.Scanner;

public class Main {
    public static void main (String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int sum = 0;
        int[][] vec = new int[n][m];
        // 初始化并计算数组元素和
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                vec[i][j] = scanner.nextInt();
                sum += vec[i][j];
            }
        }

        // 行前缀和
        int[] horizontoal = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                horizontoal[i] += vec[i][j];
            }
        }
        // 列前缀和
        int[] vertical = new int[m];
        for (int j = 0; j < m; j++) {
            for (int i = 0; i < n; i++) {
                vertical[j] += vec[i][j];
            }
        }

        int res = Integer.MAX_VALUE;
        // 水平切分
        int horizontoalCut = 0; // 前 i 行元素的和
        for (int i = 0; i < n; i++) {
            horizontoalCut += horizontoal[i];
            res = Math.min(res, Math.abs(horizontoalCut - (sum - horizontoalCut)));
        }
        // 垂直切分 
        int verticalCut = 0; // 前 j 列元素的和
        for (int j = 0; j < m; j++) {
            verticalCut += vertical[j];
            res = Math.min(res, Math.abs(verticalCut - (sum - verticalCut)));
        }
        System.out.println(res);
        scanner.close();
    }
}

进阶

前缀和(优化)

posted @ 2025-10-13 18:06  Nickey103  阅读(4)  评论(0)    收藏  举报