BZOJ 2228 礼物(gift)(最大子长方体)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2228

题意:给出一个只含有NP两种字母的长方体。从中找出只含有字母N的长方体,造型为a*a*b,即必须有两个正方形的底。在此基础上使得a*b最大?

思路:首先对于p*q*r的长方体,可以枚举a*a这个面在p*q、p*r、q*r。不妨现在假设a*a在q*r这个面上。那么对于p个面,我们用f[i][j][k]表示在第i个面上,以(j,k)为右下角的最大正方形的边长。之后,对于p个面的每个(j,k)位置,就好比是给出一个数列,找到一个区间[L,R],使得区间最小值与区间长度之积最大。

 




int p,q,r,f[N][N][N];
char s[N][N][N],s1[N][N][N];




int cal(int a[],int n)
{
    int left[N],right[N],ans=0,i;
    a[0]=a[n+1]=-1;
    FOR1(i,n) left[i]=right[i]=i;
    FOR1(i,n)
    {
        while(a[i]<=a[left[i]-1]) left[i]=left[left[i]-1];
    }
    FORL1(i,n) 
    {
        while(a[i]<=a[right[i]+1]) right[i]=right[right[i]+1];
    }
    FOR1(i,n) upMax(ans,(right[i]-left[i]+1)*a[i]);
    return ans;
}




int cal(int p,int q,int r,char s[N][N][N])
{
    int i,j,k;
    int ans=0;
    FOR1(i,p)
    {
        FOR1(j,q) FOR1(k,r) 
        {
            if(s[i][j][k]=='P') f[i][j][k]=0;
            else 
            {
                f[i][j][k]=min(f[i][j-1][k],f[i][j][k-1]);
                f[i][j][k]=min(f[i][j][k],f[i][j-1][k-1]);
                f[i][j][k]++;
            }
        }
    }
    int a[N];
    FOR1(j,q) FOR1(k,r) 
    {
        FOR1(i,p) a[i]=f[i][j][k];
        upMax(ans,cal(a,p));
    }
    return ans;
}


int main()
{
    RD(q,p,r);
    int i,j,k,ans=0;
    FOR1(i,p) FOR1(j,q) RD(s[i][j]+1);
    upMax(ans,cal(p,q,r,s));
    FOR1(j,q) FOR1(i,p) FOR1(k,r) s1[j][i][k]=s[i][j][k];
    upMax(ans,cal(q,p,r,s1));
    FOR1(k,r) FOR1(i,p) FOR1(j,q) s1[k][i][j]=s[i][j][k];
    upMax(ans,cal(r,p,q,s1));
    PR(ans<<2);
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值