您的位置:首页 > 其它

[NOIP2017模拟]Cut

2017-10-06 16:29 309 查看
题目背景

SOURCE:NOIP2015-SHY-7

题目描述

今天是ABC的生日,他制作了一个巧克力蛋糕!你可以把它理解成一个有 R×C 个小格子组成的矩形。每个格子上都有一些巧克力 chips ,第 i 行,第 j 列的格子上有 A[i][j] 个巧克力 chips 。

有 A×B 个人要出席 ABC 的生日晚会(包括ABC自己),每个人都想得到一块蛋糕。于是他想要把他的蛋糕切成 A×B 个小块。首先,他先横着切(A-1)刀,蛋糕就变成了 A 条,然后,对于每一条,他都纵着切(B-1)刀,就的到了(A×B)个小块。为了体现自己的大度, ABC 决定最后选蛋糕,而 ABC 的朋友就不会这么想了,他们总是拿走巧克力最多的蛋糕,所以,ABC 得到的蛋糕永远是巧克力最少的那一块。

聪明的 ABC 很喜欢吃巧克力,他想得到更多的巧克力,但是他正忙着准备自己的生日晚会,于是他来寻求你的帮助,希望你不要让他失望。

输入格式

第一行一个四个整数 R,C,A,B 。

接下来 R 行,每行 C 个数,描述每个格子上的巧克力数。

输出格式

输出一个整数,表示 ABC 最多能得到的巧克力数。

样例数据

输入

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

备注

【样例说明】

12|21

−−−

3|111

−−−

201|3

−−−

1 1 | 1 1

1 1 | 1 1

【数据范围】

对 30% 的输入数据: 1≤R,C≤100,1≤A≤R,1≤B≤C;

对 100% 的输入数据:1≤R,C≤500,1≤A≤R,1≤B≤C,A[i][j]≤4000

分析:二分,check直接模拟就好(详见代码)。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}

int R,c,a,b,tot,ans;
int cake[510][510],lin[510];

bool check(int x)
{
int minline=x*b,num1=0,num2=0,cnt1=0,cnt2=0,bj=0;//每一条至少需要x*b那么多chip,不然都不够分成b个x
for(int i=1;i<=R;++i)
{
num1+=lin[i];//加一行
if(num1>=minline)//判断从这一行切开在总数上是否满足大于x*b
{//如果能再看这一整条能否切成b块
for(int j=1;j<=c;++j)
{
for(int k=bj+1;k<=i;++k)
num2+=cake[k][j];

if(num2>=x)//只要这块蛋糕大于x就可以切断
{
cnt2++;
num2=0;
}
}

if(cnt2<b)//不到b块就要继续加行
{
cnt2=0;
num2=0;
}
else//到b块就可以切断
{
cnt1++;
num1=0;
num2=0;
cnt2=0;
bj=i;
}
}
}

return cnt1>=a;//判断能否切出a条
}

int main()
{
freopen("cut.in","r",stdin);
freopen("cut.out","w",stdout);

R=getint();c=getint();a=getint();b=getint();
for(int i=1;i<=R;++i)
for(int j=1;j<=c;++j)
{
cake[i][j]=getint();
tot+=cake[i][j];
lin[i]+=cake[i][j];//记一下一行有多少
}

int l=0,r=tot/(a*b)+1,mid;
while(l<=r)
{
mid=l+r>>1;
if(check(mid))
{
ans=mid;
l=mid+1;
}
else
r=mid-1;
}

cout<<ans<<'\n';
return 0;
}


本题结。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: