Link
~~(又一个)~~二分答案。
题目描述
今天是Bessie的生日,他买了一个蛋糕和朋友们一起分享,蛋糕可以看成是一个R行C列的表格,共有R*C个格子,每个格子都有一个0至9的数字,表示该格子蛋糕拥有的巧克力。现在Bessie要把蛋糕横的切3刀再竖的切3刀,由于Bessie刀法厉害,所以每个格子蛋糕都是完整的,显然蛋糕会被切成16份,然后Bessie和他的15个朋友们每人拿一份,Bessie比较客气,总是等其他朋友拿完了,Bessie拿最后剩下的那一份。Bessie的朋友们都很不客气,都是挑最多巧克力的那份去拿,于是Bessie最后拿到手的那份蛋糕总是巧克力总和最少的。Bessie心想:既然自己总是最后拿蛋糕,那应该怎么切蛋糕,才能使得自己拿的那部分蛋糕的有尽量多的巧克力呢?这个问题自然是你的任务了。
Input
第一行,个两整数R,C。
接下来有R行,每行有C个整数,每个整数范围是0至9
Output
一个整数,表示Bessie最后拿到的蛋糕最多可以有多少巧克力。
数据范围
40%的数据, 4 <= R,C <= 10。
60%的数据, 4 <= R,C <= 20。
100%的数据, 4 <= R,C <= 75。
题目大意
给出一个r*c的数字矩阵,横切三刀,竖切三刀(没有弯曲部分),求如何切使得最小一块矩阵和最大。
这数据范围…暴力走起。
暴力枚举竖切三刀的位置,然后二分答案,判断这3刀切 是否可以凑出横着4刀切大于答案的。
#include<cstdio>
#include<iostream>
using namespace std;
int s[80][80],RRR,maxx,r,c,l1,l2,l3,mid;
char ll;
bool check(){
int k1=0,k2=0,k3=0,k4=0,lt=0;
for(int i = 1; i <= r; ++i){
k1+=s[i][l1]; //统计
k2+=s[i][l2]-s[i][l1];
k3+=s[i][l3]-s[i][l2];
k4+=s[i][c]-s[i][l3];
if(k1>=mid&&k2>=mid&&k3>=mid&&k4>=mid){ //可以切
k1=k2=k3=k4=0;
lt++;
}
}
return lt>=4;
}
void work(){
int l = 0, rr = RRR;
while(l<rr){ //二分
mid = (l+rr+1) >> 1;
if(check()==1) l = mid;
else rr = mid - 1;
}
maxx = max(maxx,l);
}
int main(){
scanf("%d%d",&r,&c);
for(int i = 1; i <= r; ++i)
for(int j = 1; j <= c; ++j){
ll=getchar();
while(ll>'9'||ll<'0') ll = getchar();
RRR += ll-48;
s[i][j] = s[i][j-1]+ll-48; //前缀和
}
RRR=RRR/16;
for(l1 = 1; l1 < c; ++l1) //枚举
for(l2 = l1+1; l2 < c; ++l2)
for(l3 = l2+1; l3 < c; ++l3)
work();
printf("%d",maxx);
}
来源:CSDN
作者:SSL_HKY
链接:https://blog.csdn.net/qq_42937087/article/details/103533080