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