BZOJ [Ctsc2002] Award 颁奖典礼 解题报告

[Ctsc2002] Award 颁奖典礼

Description

IOI2002的颁奖典礼将在YONG-IN Hall隆重举行。人们在经历了充满梦幻的世界杯之后变得更加富于情趣。为了使颁奖典礼更具魅力,有人建议在YONG-IN Hall中搭建一个I字型的颁奖台,以此代表信息学Informatics。考虑到比赛的赞助商们可能要在YONG-IN Hall中摆设了许多展示台,他们可能不愿意移动展示台的位置。你作为IOI2002的金牌得主自然地成为了他们求助的对象。 YONG-IN Hall是一个矩形的网格区域。每个赞助商的展示台都占据了若干个单位网格。I型颁奖台将正向搭建,且平行于YONG-IN Hall的边缘。I型颁奖台是由三个矩形相接叠成的,其中上方和下方的矩形的两侧必须都超出中间的矩形,否则将被误解成T, L, J等字母。

例如:

这是两个合法的I型颁奖台,而以下三种情况均不合法:

希望你编程寻找面积最大的I型颁奖台,使其不覆盖任何展示台。

Input

第一行包含两个正整数n, m(1<=n,m<=200),分别表示YONG-IN Hall的矩形网格区域的行数和列数。以下n行每行包含m个数字,非0即1,每个数字描述一个单位网格,1表示该单位网格存在展示台,0表示该单位网格不存在展示台。

Output

仅包含一个正整数,表示最大的I型颁奖台的面积。如果不存在合法的I型颁奖台,则输出0。


大力DP+前缀和优化

把字母"I"看成三个矩形
\(dp[i][k][l][r]\)表示第\(i\)行做到第\(k\)个矩形左边界为\(l\)右边界为\(r\)的最大面积

枚举四维后我们发现不换矩形可以\(O(1)\)转移

但换矩形得多枚举两维,于是用RMQ前缀和先处理一下作为优化


Code:
DewOS:我怀疑我自己程序写的有问题但它过了就不管啦

#include <cstdio>
#include <cstring>
int max(int x,int y){return x>y?x:y;}
const int N=202;
int dp[3][N][N][N],f[2][N][N],f0[N][N];
int n,m,is[N][N],ans;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&is[i][j]);
            f0[i][j]=f0[i][j-1]+is[i][j];
        }
    memset(dp,-0x3f,sizeof(dp));
    memset(f,-0x3f,sizeof(f));
    memset(dp[0][0],0,sizeof(dp[0][0]));
    for(int i=1;i<=n;i++)
        for(int k=2;k>=0;k--)
        {
            for(int l=1;l<=m;l++)
                for(int r=l;r<=m;r++)
                {
                    if(f0[i][r]==f0[i][l-1])
                    {
                        if(!k) dp[k][i-1][l][r]=max(dp[k][i-1][l][r],0);
                        dp[k][i][l][r]=dp[k][i-1][l][r]+(r+1-l);
                        if(k==1) dp[k][i][l][r]=max(dp[k][i][l][r],f[k-1][l-1][r+1]+(r+1-l));
                        else if(k==2) dp[k][i][l][r]=max(dp[k][i][l][r],f[k-1][l+1][r-1]+(r+1-l));
                    }

                }
            if(!k)
            {
                for(int l=1;l<=m;l++)
                    for(int r=m;r>=l;r--)
                        f[k][l][r]=max(dp[k][i][l][r],max(f[k][l][r+1],f[k][l-1][r]));
            }
            else if(k==1)
            {
                for(int l=m;l;l--)
                    for(int r=l;r<=m;r++)
                        f[k][l][r]=max(dp[k][i][l][r],max(f[k][l][r-1],f[k][l+1][r]));
            }
            else
            {
                for(int l=1;l<=m;l++)
                    for(int r=l;r<=m;r++)
                        ans=max(ans,dp[k][i][l][r]);
            }
        }
    printf("%d\n",ans);
    return 0;
}


2018.7.26

posted @ 2018-07-26 15:32  露迭月  阅读(289)  评论(0编辑  收藏  举报