zoukankan      html  css  js  c++  java
  • 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
    ",ans);
        return 0;
    }
    
    

    2018.7.26

  • 相关阅读:
    linux下进度条的简单实现
    简单vim配置
    Linux下find指令
    Python学习笔记十三_操作数据库
    Python学习笔记十二_常用模块
    Python学习笔记十一_函数返回多值、列表生成式、循环多变量、入参格式声明
    Python学习笔记十_模块、第三方模块安装、模块导入
    Python函数及json练习_双色球
    Python函数及json练习_商品管理
    Python json练习_读写文件函数
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9372076.html
Copyright © 2011-2022 走看看