【JZOJ 3918】 蛋糕

Description

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

Analysis

看到双最优先考虑二分啦
二分出一个答案,而后枚举哪三列切我们可以O(n)扫一遍很快地知道行最多切几刀也可以二分,但因为r,c很小所以其实两个跑出来差不多
O(n4logn) O(n3log2n)

Code

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int N=80;
int lim,n,m,a[N][N];
int s(int x1,int y1,int x2,int y2)
{
    return a[x2][y2]-a[x2][y1-1]-a[x1-1][y2]+a[x1-1][y1-1];
}
bool pd(int x,int y,int z)
{
    int i,j,k;
    for(i=1;i<=n+1;i++)
        if(s(1,1,i,x)>=lim && s(1,x+1,i,y)>=lim
        && s(1,y+1,i,z)>=lim && s(1,z+1,i,m)>=lim) break;
    if(i>n) return 0;
    for(j=i+1;j<=n+1;j++)
        if(s(i+1,1,j,x)>=lim && s(i+1,x+1,j,y)>=lim
        && s(i+1,y+1,j,z)>=lim && s(i+1,z+1,j,m)>=lim) break;
    if(j>n) return 0;
    for(k=j+1;k<=n+1;k++)
        if(s(j+1,1,k,x)>=lim && s(j+1,x+1,k,y)>=lim
        && s(j+1,y+1,k,z)>=lim && s(j+1,z+1,k,m)>=lim) break;
    if(k>n) return 0;
    if(s(k+1,1,n,x)>=lim && s(k+1,x+1,n,y)>=lim
    && s(k+1,y+1,n,z)>=lim && s(k+1,z+1,n,m)>=lim) return 1;
    return 0;
}
bool check()
{
    fo(i,1,m-3)
        fo(j,i+1,m-2)
            fo(k,j+1,m-1)
                if(pd(i,j,k)) return 1;
    return 0;
}
int main()
{
    scanf("%d %d\n",&n,&m);
    int l=0,r=0;
    fo(i,1,n)
    {
        fo(j,1,m)
        {
            int x=getchar()-'0';
            r+=x;
            a[i][j]=x+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
        }
        scanf("\n");
    }
    r=r/16+1;
    while(l<r-1)
    {
        lim=(l+r)>>1;
        if(check()) l=lim;
        else r=lim;
    }
    printf("%d",l);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值