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

    题目描述

    小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)<=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想要知道,他能画出的最大幸运度是多少。

    输入输出格式

    输入格式:

    输入文件penman.in的第一行包含两个正整数n和m,分别表示矩阵的行数和列数。

    接下来n行,每行有m个整数,第i+1行的第j个数表示格子(j,n-i+1)的幸运值。

    输出格式:

    输出到文件penman.out中,输出一个整数T,表示小E能够获得的最大幸运度。

    输入输出样例

    输入样例#1:
    【样例输入1】
    3 13 
    1 1 -1 -1 1 -1 1 1 1 -1 1 1 1 
    1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 
    1 -1 -1 1 1 -1 1 1 1 -1 1 1 1 
    
    
    
    
    【样例输入2】
    3 13
    -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
    -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
    -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
    
    
    输出样例#1:
    【样例输出1】
    24 
    【样例输出2】
    -20
    

    说明

    样例1

    样例2

    数据范围

    对于所有的测试数据,保证n≥3,m≥12。

    超级丧病的一道题,难怪没什么人写..
    首先看题就看了40分钟才懂..
    好像还有一个地方题目描述和样例不吻合???
    还是忽略这个细节,按样例来.
    按照列来dp.
    dp[0/1][type][i][j]代表这一列选了的最上面是i,最下面是j的最大权值.
    把列滚动.type表示这是第几种情况.
    那么1,2,3分别表示’N’的前面一个矩形和中间一坨和后面一个矩形.
    4,5,6表示’O’.7,8,9表示’I’.
    中间还有两坨空白.
    那么OI和空白是很好搞的,直接按照题意转移即可.
    主要是’N’比较难搞.
    13其实也不难,决策单调性,可以做到n^2.
    2想了半天还是只会n^3.
    看了下题解,感觉有点套路..
    设转移为(2,k,t)->(2,i,j),其中k<=i<=t+1,j>=t。我们将这个分成两种情况:
    1i=t+1:设dp[t+1][t+1]=max(f[2][1][t],f[2][2][t],……,f[][2][t-1][t],f[2][t][t])。最后用dp[i][j]更新dp[i][j+1],那么直接用dp[i][j]更新当前的f[2][i][j];
    2k<=i<=t:比如k=2,t=6,那么这个可以更新
    [2,6],[2,7],……,[2,n]
    [3,6],[3,7],……,[3,m]
    ……
    [6,6],[6,7],……,[6,n]
    因此设dp[i][j]=f[2][i][j],之后用dp[i][j]更新dp[i+1][j],最后再用dp[i][j]更新dp[i][j+1]即可。这两个更新的顺序不能反。反了的话就会出很多不合法的情况,这个可以手画一下.
    其实就是先O(n)更新一段,O(n)更新另一段,因为这是取最大值,所以是可以间接更新的.


      1 #include<bits/stdc++.h>
      2 #define inf 1000000000
      3 using namespace std;
      4 int f[2][10][155][155],kong[2][2],ans=-inf,a[510][510],dp[155][155];
      5 void updata(int &x,int y){x=x<y?y:x;}
      6 int main(){
      7   freopen("!.in","r",stdin);
      8   freopen("!.out","w",stdout);
      9   int n,m;
     10   scanf("%d%d",&n,&m);
     11   for(int i=1;i<=n;i++)
     12     for(int j=1;j<=m;j++)
     13       scanf("%d",&a[j][i]),a[j][i]+=a[j][i-1];
     14   int t=0,tt=1;
     15   memset(f[tt],-127/3,sizeof(f[tt]));
     16   kong[tt][0]=kong[tt][1]=-inf;
     17   for(int i=1;i<=m;i++){
     18     memset(f[t],-127/3,sizeof(f[t]));
     19     kong[t][0]=kong[t][1]=-inf;
     20     for(int j=1;j<=n;j++)
     21       for(int k=j;k<=n;k++)
     22     f[t][1][j][k]=f[tt][1][j][k]+a[i][k]-a[i][j-1];
     23     for(int j=1;j<=n;j++)
     24       for(int k=j;k<=n;k++)
     25     f[t][1][j][k]=max(f[t][1][j][k],a[i][k]-a[i][j-1]);
     26     //---------------------------------------------------------第一种
     27     for(int j=1;j<=n;j++){
     28       int zd=f[tt][1][j][n],sp=n;
     29       for(int k=n-1;k>=j;k--){
     30     f[t][2][j][k]=zd+a[i][k]-a[i][j-1];
     31     if(f[tt][1][j][k]>zd) zd=f[tt][1][j][k],sp=k;
     32       }
     33     }
     34     memset(dp,-127/3,sizeof(dp));
     35     for(int j=2;j<=n;j++)
     36       for(int k=1;k<j;k++)
     37     updata(dp[j][j],f[tt][2][k][j-1]);
     38     for(int j=1;j<=n;j++)
     39       for(int k=j+1;k<=n;k++)
     40     updata(dp[j][k],dp[j][k-1]);
     41     for(int j=1;j<=n;j++)
     42       for(int k=j;k<=n;k++)
     43     updata(f[t][2][j][k],dp[j][k]+a[i][k]-a[i][j-1]);
     44     for(int j=1;j<=n;j++)
     45       for(int k=j;k<=n;k++)
     46     dp[j][k]=f[tt][2][j][k];
     47     for(int j=1;j<=n;j++)
     48       for(int k=1;k<j;k++)
     49     updata(dp[k+1][j],dp[k][j]);
     50     for(int j=1;j<=n;j++)
     51       for(int k=j;k<=n;k++)
     52     updata(dp[j][k+1],dp[j][k]);
     53     for(int j=1;j<=n;j++)
     54       for(int k=j;k<=n;k++)
     55     updata(f[t][2][j][k],dp[j][k]+a[i][k]-a[i][j-1]);
     56     //---------------------------------------------------------第二种
     57     for(int k=n;k>1;k--){
     58       int zd=f[tt][2][k][k],sp=k;
     59       for(int j=k-1;j>=1;j--){
     60     f[t][3][j][k]=zd+a[i][k]-a[i][j-1];
     61     if(f[tt][2][j][k]>zd) zd=f[tt][2][j][k],sp=j;
     62       }
     63     }
     64     for(int j=1;j<=n;j++)
     65       for(int k=j;k<=n;k++)
     66     updata(f[t][3][j][k],f[tt][3][j][k]+a[i][k]-a[i][j-1]);
     67     //---------------------------------------------------------第三种
     68     int zd=kong[tt][0];
     69     for(int j=1;j<=n;j++)
     70       for(int k=j;k<=n;k++)
     71     updata(zd,f[tt][3][j][k]);
     72     kong[t][0]=zd;
     73     //---------------------------------------------------------N O 之间的空
     74     for(int j=1;j<=n;j++)
     75       for(int k=j+2;k<=n;k++)
     76     f[t][4][j][k]=kong[tt][0]+a[i][k]-a[i][j-1];
     77     //---------------------------------------------------------O 的第一部分
     78     for(int j=1;j<=n;j++)
     79       for(int k=j+2;k<=n;k++){
     80     updata(f[t][5][j][k],f[tt][4][j][k]+a[i][k]-a[i][k-1]+a[i][j]-a[i][j-1]);
     81     updata(f[t][5][j][k],f[tt][5][j][k]+a[i][k]-a[i][k-1]+a[i][j]-a[i][j-1]);
     82       }
     83     //---------------------------------------------------------O 的第二部分
     84     for(int j=1;j<=n;j++)
     85       for(int k=j+2;k<=n;k++)
     86     f[t][6][j][k]=f[tt][5][j][k]+a[i][k]-a[i][j-1];
     87     //---------------------------------------------------------O 的第三部分
     88     zd=kong[tt][1];
     89     for(int j=1;j<=n;j++)
     90       for(int k=j;k<=n;k++)
     91     updata(zd,f[tt][6][j][k]);
     92     kong[t][1]=zd;
     93     //---------------------------------------------------------N O 之间的空
     94     for(int j=1;j<=n;j++)
     95       for(int k=j+2;k<=n;k++){
     96     int tmp=a[i][k]-a[i][k-1]+a[i][j]-a[i][j-1];
     97     f[t][7][j][k]=kong[tt][1]+tmp;
     98     updata(f[t][7][j][k],f[tt][7][j][k]+tmp);
     99       }
    100     //---------------------------------------------------------I 的第一部分
    101     for(int j=1;j<=n;j++)
    102       for(int k=j+2;k<=n;k++){
    103     int tmp=a[i][k]-a[i][j-1];
    104     f[t][8][j][k]=f[tt][7][j][k]+tmp;
    105     updata(f[t][8][j][k],f[tt][8][j][k]+tmp);
    106       }
    107     //---------------------------------------------------------I 的第二部分
    108     for(int j=1;j<=n;j++)
    109       for(int k=j+2;k<=n;k++){
    110     int tmp=a[i][k]-a[i][k-1]+a[i][j]-a[i][j-1];
    111     f[t][9][j][k]=f[tt][8][j][k]+tmp;
    112     updata(f[t][9][j][k],f[tt][9][j][k]+tmp);
    113     updata(ans,f[t][9][j][k]);
    114       }
    115     swap(t,tt);
    116   }
    117   printf("%d",ans);
    118   return 0;
    119 }
  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/pantakill/p/7502668.html
Copyright © 2011-2022 走看看