题目大意:有一个矩形巧克力蛋糕,可以看作是一个RxC的矩阵;现在要切成A行B列;最后只能剩下一块最小的,求最小的最大值
- 第一眼最小的最大值,一般题目给的最小的最大值,或者最大的最小值,或者是最大值,最小值,都考虑一下二分;
对答案进行二分,分析一下边界条件,由于0的存在,我们把左边界设为0,右边界设为最大值500x500x4000;
核心逻辑:
x为当前二分的值,cnt为被分出来的部分的个数;
-
先定义一个sum变量存储当前位置的和
-
从第一行开始考虑,依次往后加,如果sum>=x,说明到这里可以被分为一个部分,cnt自增,sum重置为0,继续往后搜索,直到这行末尾。
-
到了末尾如果当前的部分数cnt小于B,说明这行的数字太小,不够分,再用一个flag来记录需要往上搜索的行数,flag自增;
-
到了末尾如果当前部分数cnt大于等于B,说明可以分,此时flag重置为0;
-
继续搜索下一行,sum和cnt重置为0;
代码如下:
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
using namespace std;
#define ll long long
const int maxn=1e5+7;
int row, col, a, b,grid[505][505];
bool check(int x){
int flag = 0, sum = 0, cnt = 0, cntrow = 0;
for (int i = 1; i <= row;++i){
for (int j = 1; j <= col;++j){
//再写一个循环来记录上flag行
for (int k = 0; k <= flag;++k){
sum += grid[i-k][j];
}
//记录分成部分的个数
if(sum>=x){
sum = 0;
cnt++;
}
}
//记录行数
if(cnt<b){
flag++;
}else{
flag = 0;
cntrow++;
}
cnt = 0;
sum = 0;
}
if(cntrow>=a)
return true;
return false;
}
int read() {
int res = 0; int f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
res = (res << 3) + (res << 1) + (ch ^ 48);
ch = getchar();
}
return res*f;
}
int main(){
IOS;
row = read();
col = read();
a = read();
b = read();
for (int i = 1; i <= row;++i){
for (int j = 1; j <= col;++j){
grid[i][j] = read();
}
}
int l = 0, r = 1000000000;
while(l<=r){
int mid = l + r >> 1;
if(check(mid)){
l = mid + 1;
}else{
r = mid - 1;
}
}
cout << r;
return 0;
}