题目描述

黄学长昨晚CF强势AK,怒踩Tourist,这势必要进行庆祝,于是庆祝专用蛋糕就这样诞生了,这是一块矩形蛋糕,它由N×M个小蛋糕组成,每个蛋糕的美味指数为Tij。
为了把蛋糕分给众人,黄学长决定横着切A−1刀,再把得到的A块各竖着切B−1刀,分成B块,这样一共有A×B块。为了使大家都高兴,他希望让美味指数之和最少的那个蛋糕的美味指数最大。请你告诉他这个值吧。注意,你不能把小蛋糕切碎。

输入

输入第一行四个数N,M,A,B;
接下来N行,每行M个整数数。

输出

输出一行,表示最小值的最大值。

样例输入

5 4 4 2
1 2 2 1
3 1 1 1
2 0 1 3
1 1 1 1
1 1 1 1

样例输出

3

提示

对于100%的数据,有1≤N,M≤500,0≤Tij≤4000,1≤A≤N,1≤B≤M。

思路:

二分最小值,check能不能实现。

check的时候枚举每一次横切的位置,有了这个位置就可以看b-1次纵切可不可以实现。如果可以,这次横切的位置就合适,继续向下进行。

//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5;
const int inf=0x3f3f3f3f;
const int mod=19961107;
const double eps=2e-9;
int a[505][505],n,m,sum[505][505],x,y;

bool check(int tag)
{
    int p=1,q;
    for(int c=0;c<x;)
    {
        for(int i=1;i<=n;i++)
        {
            if(p+i>n+1) return false;
            int d=0;
            q=1;
            for(int j=1;j+q-1<=m;j++)
            {
                if(sum[p+i-1][q+j-1]-sum[p+i-1][q-1]-sum[p-1][q+j-1]+sum[p-1][q-1]>=tag)
                {
                    q+=j;
                    d++;
                    j=0;
                }
            }
            if(d>=y)
            {
                p+=i;
                c++;
                break;
            }
        }
        if(!c) return false;
    }
    return true;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
#endif
    cin>>n>>m>>x>>y;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
        }
    }
    //check(3);
    int l=0,r=1e9;
    while(l<r)
    {
        int mid=(l+r+1)/2;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    cout<<l<<endl;
    return 0;
}
01-23 21:15