Tips:这是一个矩阵前缀和的实例,有关前缀和请看我上一篇
问题描述:
小美有一个矩形的蛋糕,共分成了 n 行 m 列,共 n * m 个区域,每个区域是一个小正方形,已知蛋糕每个区域都有一个美味度。她想切一刀把蛋糕切成两部分,自己吃一部分,小团吃另一部分。
小美希望两个人吃的部分的美味度之和尽可能接近,请你输出|s1 - s2|的最小值。(其中 s1 代表小美吃的美味度,s2 代表小团吃的美味度)。 请务必保证,切下来的区域都是完整的,即不能把某个小正方形切成两个小区域。
来源:卡码网130题
思路:只有一刀,将一个矩阵一分为二,只有两种切法,一个是横着切,一个竖着切。这就可以利用前缀和。比如我们在第i行一分为二,那么这两个部分的插值就可以表示为上半部分:以[0][0]为左上角,右下角[i][j]的矩阵值。下半部分:以[i+1][0]为左上角,右下角[n-1][m-1]的矩阵值。差值表示:
具体代码:
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main() {
int n,m;
cin >> n>>m;
vector<vector<int>> matrix(n,vector<int>(m));
//保存前缀和
vector<vector<int>> sum_matrix(n+1,vector<int>(m+1,0));
//int sum = 0;
for(int i = 0;i < n;++i) {
for(int j = 0;j < m;++j) {
cin >> matrix[i][j];
//sum += matrix[i][j];
sum_matrix[i+1][j+1] = matrix[i][j] + sum_matrix[i][j+1] + sum_matrix[i+1][j] - sum_matrix[i][j];
}
}
int res = INT_MAX;
//开始切蛋糕
//竖着切蛋糕 两个人的差距最小
for(int j = 1;j <= m;++j) {
int s1 = sum_matrix[n][j];
int s2 = sum_matrix[n][m] - s1;
res = min(res,abs(s1-s2));
}
//横着切蛋糕,两个人差距最小
for(int i = 1;i <= n;++i) {
int s1 = sum_matrix[i][m];
int s2 = sum_matrix[n][m] - s1;
res = min(res,abs(s1-s2));
}
cout << res << endl;
}
输入:
2 3
1 1 4
5 1 4
输出:
0