201.小M的蛋糕切割问题

4 阅读3分钟

小M的蛋糕切割问题

问题描述

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

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

问题理解

我们需要将一个 n×m 的矩形蛋糕切成两部分,使得两部分的美味度之和尽量接近。切割必须是完整的,即不能把某个小正方形切成两个小区域。我们的目标是找到一种切割方式,使得两部分的美味度之和的差值最小。

数据结构选择

由于我们处理的是一个二维数组,我们可以直接使用二维数组来存储蛋糕的美味度。

算法步骤

  1. 计算总和:首先计算整个蛋糕的美味度总和 totalSum
  2. 水平切割:遍历所有可能的水平切割线(从第1行到第n-1行),计算切割线上方的部分的美味度总和 sum1,然后用 totalSum - sum1 计算下方的部分的美味度总和 sum2,并计算差值 diff,更新最小差值 minDiff
  3. 垂直切割:遍历所有可能的垂直切割线(从第1列到第m-1列),计算切割线左侧的部分的美味度总和 sum1,然后用 totalSum - sum1 计算右侧的部分的美味度总和 sum2,并计算差值 diff,更新最小差值 minDiff
  4. 返回结果:最终返回最小差值 minDiff

详细步骤

  1. 计算总和

    • 遍历整个二维数组,累加所有元素的值,得到 totalSum
  2. 水平切割

    • 对于每一行 i(从1到n-1),计算切割线上方的部分的美味度总和 sum1
    • 计算切割线下方的部分的美味度总和 sum2,即 totalSum - sum1
    • 计算差值 diff,即 |sum1 - sum2|
    • 更新最小差值 minDiff
  3. 垂直切割

    • 对于每一列 j(从1到m-1),计算切割线左侧的部分的美味度总和 sum1
    • 计算切割线右侧的部分的美味度总和 sum2,即 totalSum - sum1
    • 计算差值 diff,即 |sum1 - sum2|
    • 更新最小差值 minDiff
  4. 返回结果

    • 返回 minDiff,即美味度差的最小值。

solution完整代码

        // 计算整个蛋糕的美味度总和
        int totalSum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                totalSum += a[i][j];
            }
        }

        int minDiff = Integer.MAX_VALUE;

        // 尝试所有水平切割线
        for (int i = 1; i < n; i++) {
            int sum1 = 0;
            for (int row = 0; row < i; row++) {
                for (int col = 0; col < m; col++) {
                    sum1 += a[row][col];
                }
            }
            int sum2 = totalSum - sum1;
            int diff = Math.abs(sum1 - sum2);
            minDiff = Math.min(minDiff, diff);
        }

        // 尝试所有垂直切割线
        for (int j = 1; j < m; j++) {
            int sum1 = 0;
            for (int col = 0; col < j; col++) {
                for (int row = 0; row < n; row++) {
                    sum1 += a[row][col];
                }
            }
            int sum2 = totalSum - sum1;
            int diff = Math.abs(sum1 - sum2);
            minDiff = Math.min(minDiff, diff);
        }

        return minDiff;