小美的蛋糕切割(卡码网周赛第二十一期(23年美团笔试真题))
题目描述
小美有一个矩形的蛋糕,共分成了 n 行 m 列,共 n * m 个区域,每个区域是一个小正方形,已知蛋糕每个区域都有一个美味度。她想切一刀把蛋糕切成两部分,自己吃一部分,小团吃另一部分。 小美希望两个人吃的部分的美味度之和尽可能接近,请你输出|s1 - s2|的最小值。(其中 s1 代表小美吃的美味度,s2 代表小团吃的美味度)。 请务必保证,切下来的区域都是完整的,即不能把某个小正方形切成两个小区域。
输入
第一行输出两个正整数 n 和 m(1 <= n, m <= 10^3),代表蛋糕区域的行数和列数。接下来的 n 行,每行输入 m 个正整数 aij(1 <= aij <= 10^4),用来表示每个区域的美味度。
输出
一个整数,代表|s1-s2|的最小值。
样例输入
2 3
1 1 4
5 1 4
样例输出
0
提示
把蛋糕像这样切开:
1 1 | 4
5 1 | 4
左边蛋糕美味度之和是 8 右边蛋糕美味度之和是 8 所以答案是 0。
题解1(C++版本)
// 前缀和
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 10;
int n, m;
LL row[N], col[N]; // 将蛋糕切成两部分,有横着切和竖着切两种方式
LL Min(LL A, LL B){
return A < B ? A: B;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1, x; i <= n; i++){
for(int j = 1; j <= m; j++){
scanf("%d", &x);
col[j] = col[j] + x; // 列之和
row[i] = row[i] + x; // 行之和
}
}
for(int i = 1; i <= m; i++) col[i] += col[i - 1];
LL ans = 1e18 + 10;
for(int j = 2; j <= m; j++){
LL a = col[j - 1];
LL b = col[m] - a;
ans = Min(ans, abs(b - a));
}
for(int i = 1; i <= n; i++) row[i] += row[i - 1];
for(int i = 2; i <= n; i++){
LL a = row[i - 1];
LL b = row[n] - a;
ans = Min(ans, abs(b - a));
}
printf("%lld\n", ans);
return 0;
}