题目大意:有一个矩形巧克力蛋糕,可以看作是一个RxC的矩阵;现在要切成A行B列;最后只能剩下一块最小的,求最小的最大值

- 第一眼最小的最大值,一般题目给的最小的最大值,或者最大的最小值,或者是最大值,最小值,都考虑一下二分;

对答案进行二分,分析一下边界条件,由于0的存在,我们把左边界设为0,右边界设为最大值500x500x4000;

核心逻辑:

x为当前二分的值,cnt被分出来的部分的个数;

  1. 先定义一个sum变量存储当前位置的和

  2. 从第一行开始考虑,依次往后加,如果sum>=x,说明到这里可以被分为一个部分,cnt自增,sum重置为0,继续往后搜索,直到这行末尾。 alt

  3. 到了末尾如果当前的部分数cnt小于B,说明这行的数字太小,不够分,再用一个flag来记录需要往上搜索的行数,flag自增; alt alt

  4. 到了末尾如果当前部分数cnt大于等于B,说明可以分,此时flag重置为0;

  5. 继续搜索下一行,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;
}