zoukankan      html  css  js  c++  java
  • [Noi2013]书法家

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    小E同学非常喜欢书法,他听说NOI2013已经开始了,想题一幅“NOI”的字送给大家。


    小E有一张非常神奇的纸,纸可以用一个n 行m 列的二维方格矩阵来表示,为了描述方便,我们定义矩阵左下角方格坐标为(1,1) ,右上角方格坐标为(m,n) 。矩阵的每个方格有一个整数的幸运值。在格子上面写字可以增加大家的幸运度,幸运度的大小恰好是所有被笔写到的方格的幸运值之和。现在你要在上面写上 ‘N’,‘O’,‘I’三个字母。

    下面给出3个书法字的定义:

      1.‘N’由若干(≥3)个边平行于坐标轴的矩形组成,设有K个矩形组成(标号1~K),第i个矩形的左下角方格坐标设为(Li ,Bi) ,右上角坐标设为(Ri ,Ti) ,要求满足:
    a)Li<=Ri,Bi<=Ti
    b)对任意1<i<=K,有Li=R(i-1)+1
    c)对任意3<=i<K,有B(i-1)-1<=Ti<=T(i-1),Bi<=B(i-1);" 
    d)B2>B1,T2=T1,B(K-1)=B(K),T(k-1)<T(K)


      2.‘O’由一个大矩形A,挖去一个小矩形B得到,这两个矩形的边都平行于坐标轴。设大矩形左下角的方格坐标为(u,v),长为W宽为H,则小矩形B满足左下角方格坐标为(u+1,v+1) ,长W-2 ,宽H-2。要求满足:
    a)W>=3,H>=3
    b)u>R(K)+1

      3.‘I’为3个边平行于坐标轴的从下到上的实心矩形组成,从下到上依次标号为1,2,3,第i 个矩形的左下角格子坐标设为(Pi , Qi ),右上角格子坐标设为(Gi , Hi ),要求满足:
    a)Pi<=Gi,Qi<=Hi
    b)P1=P3>u+W,G1=G3
    c)Q1=H1=Q2-1,H2+1=Q3=H3
    d)P1<P2<=G2<G1

    下图是一个‘N’,‘O’,‘I’的例子

    另外,所有画的图形均不允许超过纸张的边界。现在小E想要知道,他能画出的最大幸运度是多少。

    n<=150 m<=500

    可以按照列下来形状的不同分成11块(N分成3块,O分成3块,I分成3块,然后中间两个间隔) 然后大力DP

    N的处理比较复杂,可以开类似"一个坐标是x,另一个坐标大/小等于y的最大值"的dp数组来转移

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define rint register int
    #define INF 2000000000
    #define N 150
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int f1[2][N+5][N+5],f2[2][N+5][N+5],f3[2][N+5][N+5],f4[2],f5[2][N+5][N+5],f6[2][N+5][N+5],mx1[2][N+5][N+5],mx3[2][N+5][N+5];
    int f7[2][N+5][N+5],f8[2],f9[2][N+5][N+5],f10[2][N+5][N+5],f11[2][N+5][N+5],n,m,s[N+5][550],ans=-INF,mx2[2][N+5][N+5];
    
    inline void R(int&x,int y){y>x?x=y:0;}
    inline int sum(int x1,int y1,int x2,int y2){return s[x2][y2]+s[x1-1][y1-1]-s[x1-1][y2]-s[x2][y1-1];}
    
    void Clear(int k)
    {
        f4[k]=f8[k]=-INF;
        memset(f1[k],128,sizeof(f1[k]));
        memset(f2[k],128,sizeof(f2[k]));    
        memset(f3[k],128,sizeof(f3[k]));    
        memset(f5[k],128,sizeof(f5[k]));
        memset(f6[k],128,sizeof(f6[k]));
        memset(f7[k],128,sizeof(f7[k]));
        memset(f9[k],128,sizeof(f9[k]));
        memset(f10[k],128,sizeof(f10[k]));
        memset(f11[k],128,sizeof(f11[k]));    
        memset(mx1[k],128,sizeof(mx1[k]));
        memset(mx2[k],128,sizeof(mx2[k]));
        memset(mx3[k],128,sizeof(mx3[k]));
    }
    
    int main()
    {
        Clear(0);Clear(1);
        n=read();m=read();
        for(rint i=1;i<=n;++i)
            for(rint j=1;j<=m;++j)
                s[i][j]=read()+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        for(rint i=1,a=1,b=0;i<=m;++i)
        {
            for(rint j=1;j<=n;++j)
            {
                int Mx=mx3[b][j-1][j-1];
                for(rint k=j;k<=n;++k)
                {
                    Mx=max(Mx,mx3[b][k][j]);
                    int sum1=sum(j,i,k,i),sum2=sum(j,i,j,i)+sum(k,i,k,i);
                    R(f1[a][j][k],max(f1[b][j][k],0)+sum1);
                    R(f2[a][j][k],mx1[b][j][k+1]+sum1);
                    R(f2[a][j][k],Mx+sum1);
                    R(f3[a][j][k],mx2[b][k][j+1]+sum1);
                    R(f3[a][j][k],f3[b][j][k]+sum1);
                    R(f4[a],f3[b][j][k]);
                    R(f4[a],f4[b]);R(f8[a],f8[b]);
                    R(f8[a],f7[b][j][k]);
                    if(j+1<k)
                    {
                        R(f5[a][j][k],f4[b]+sum1);
                        R(f6[a][j][k],max(f6[b][j][k],f5[b][j][k])+sum2);
                        R(f7[a][j][k],f6[b][j][k]+sum1);
                        R(f9[a][j][k],max(f8[b],f9[b][j][k])+sum2);
                        R(f10[a][j][k],max(f9[b][j][k],f10[b][j][k])+sum1);
                        R(f11[a][j][k],max(f11[b][j][k],f10[b][j][k])+sum2);
                    }
                    R(ans,f11[a][j][k]);
                } 
            }
            for(rint j=1;j<=n;++j)
                for(rint k=n;k>=j;--k)
                    mx1[a][j][k]=max(mx1[a][j][k+1],f1[a][j][k]);
            for(rint j=n;j;--j)
                for(rint k=j;k;--k)
                    mx2[a][j][k]=max(mx2[a][j][k+1],f2[a][k][j]);
            for(rint j=1;j<=n;j++)
                for(rint k=1;k<=j;++k) 
                    mx3[a][j][k]=max(mx3[a][j][k-1],f2[a][k][j]);
            swap(a,b);Clear(a);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    关于sqlite数据库在使用过程中应该注意以下几点
    关于THREAD线程中CurrentCulture与CurrentUICulture的学习
    转:ASP.NET MVC3升级到ASP.NET MVC4
    win8 iis安装及网站发布
    转: CKEditor/CKFinder升级心得
    [更新]Windows Phone 实现类似“微博”下拉刷新效果
    EntityFramework中使用Include可能带来的问题
    [更新]Luke.Net for Pangu 盘古分词版更新
    文件大小友好显示类
    找出最慢的查询语句Find your slowest queries
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2013d2t2.html
Copyright © 2011-2022 走看看