【二分答案】jzoj蛋糕

北战南征 提交于 2019-12-14 00:03:16

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);
} 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!