JZOJ3918 蛋糕

蛋糕

题目描述:
今天是Bessie的生日,他买了一个蛋糕和朋友们一起分享,蛋糕可以看成是一个R行C列的表格,共有R*C个格子,每个格子都有一个0至9的数字,表示该格子蛋糕拥有的巧克力。现在Bessie要把蛋糕横的切3刀再竖的切3刀,由于Bessie刀法厉害,所以每个格子蛋糕都是完整的,显然蛋糕会被切成16份,然后Bessie和他的15个朋友们每人拿一份,Bessie比较客气,总是等其他朋友拿完了,Bessie拿最后剩下的那一份。Bessie的朋友们都很不客气,都是挑最多巧克力的那份去拿,于是Bessie最后拿到手的那份蛋糕总是巧克力总和最少的。Bessie心想:既然自己总是最后拿蛋糕,那应该怎么切蛋糕,才能使得自己拿的那部分蛋糕的有尽量多的巧克力呢?这个问题自然是你的任务了。

输入:
第一行,个两整数R,C。
接下来有R行,每行有C个整数,每个整数范围是0至9。

输出:
一个整数,表示Bessie最后拿到的蛋糕最多可以有多少巧克力。

这道题考虑到R和C都不大,所以就考虑暴力。
很显然二分答案然后用 O ( R 4 ) O(R^4) O(R4)的时间判断。
这过不了啊。。。其实过的了,只是这个时间复杂度算错了。
里面有个三是 C 3 C3 C3

直接上代码,没什么好说的。

#include <cstdio>
#include <cstring>
using namespace std;

const int N = 80;

inline void read(int &x)
{
	char ch = getchar();
	for(;ch < '0' || ch > '9';) ch = getchar();
	for(;ch >= '0' && ch <= '9';) x = x * 10 + (ch ^ '0'), ch = getchar();
}

char s[N];
int n,m,a[N][N],sum,l,r,mid,ans;

bool check(int mid)
{
	for(int i = 2;i <= m; ++ i)
		for(int j = i + 1;j <= m; ++ j)
			for(int k = j + 1;k <= m; ++ k)
			{
				int sum1 = 0,sum2 = 0,sum3 = 0,sum4 = 0,cnt = 0;
				for(int o = 1;o <= n; ++ o)
				{
					sum1 += a[o][i - 1],sum2 += a[o][j - 1] - a[o][i - 1],
					sum3 += a[o][k - 1] - a[o][j - 1],sum4 += a[o][m] - a[o][k - 1];
					if(sum1 >= mid && sum2 >= mid && sum3 >= mid && sum4 >= mid)
						cnt ++, sum1 = sum2 = sum3 = sum4 = 0;
					if(cnt > 3) break;
				}
				if(cnt > 3) return 1;
			}
	return 0;
}

int main()
{
	read(n), read(m);
	for(int i = 1;i <= n; ++ i)
	{
		scanf("%s",s + 1);
		for(int j = 1;j <= m; ++ j) a[i][j] = (s[j] ^ '0') + a[i][j - 1], sum += a[i][j];
	}
	
	l = 0, r = sum / 16;
	for(;l <= r;) check(mid = l + r >> 1) ? (l = mid + 1, ans = mid,1) : r = mid - 1;
	
	printf("%d\n",ans);
	return 0;
} 

千万别学我。。。这个方法很劣的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值