【二分】蛋糕

蛋糕

題目大意

把一塊R * C的巧克力蛋糕,橫着切三刀,豎着切三刀,共分成16份,然後每次拿最大的那一塊,求出最後那一塊最大的情況

輸入

一行,R 和 C

輸出

最後拿到的蛋糕最多可以有多少巧克力

輸入樣例

5 5
95998
21945
23451
99798
74083

輸出樣例

3

解題思路

這道題聽大佬說是二分答案

就是先枚舉豎的(當然也可以枚舉橫的),然後再二分每一行是否爲成立的,即可算出最優答案

程序如下

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[10001][1001],sum,ans,l,r,mid;
bool check(int a1, int a2, int a3, int mid)
{
	int p1 = 0, p2 = 0, p3 = 0, p4 = 0, k = 0;
	for(int i = 1;i <= n; ++i)
	{
		p1 += a[i][a1];
		p2 += a[i][a2] - a[i][a1];
		p3 += a[i][a3] - a[i][a2];
		p4 += a[i][m] - a[i][a3];//區間和
		if(p1 >= mid && p2 >= mid && p3 >= mid &&p4 >= mid)//判斷是否合理
		{
			p1 = 0;
			p2 = 0;
			p3 = 0;
			p4 = 0;
			k++;
		}
 	}
 	return k >= 4;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n; ++i)
		for(int j = 1;j <= m; ++j)
		{
			scanf("%1d",&a[i][j]);
			sum += a[i][j];
			a[i][j] += a[i][j - 1];//前綴和
		}
	for(int i = 1;i <= m; ++i)//枚舉豎着的
	{
		for(int j = i + 1;j <= m; ++j)
		{
			for(int k = j + 1;k <= m; ++k)
			{
				l = 0,r = sum;
				while(l <= r)//二分答案
				{
					mid = (l + r) >> 1;
					if(check(i, j, k, mid)) l = mid + 1;
					else r = mid - 1;
				}
				ans = max(ans, r);
			}
		}
	} 
	printf("%d",ans);
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章