BZOJ 3241: [Noi2013]书法家

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3241

题意:

思路:把每个字母分成三部分,两个字母之间还有空的列,所以我一共设了11个状态f[11][i][j],123表示字母N,4表示NO之间的空列,567表示O,8表示OI之间的空列,9 10 11表示I。然后按照列DP.f[t][i][j]表示状态t,最上最下的位置[i,j]的最大价值。那么我们看转移:

1:直接生成或者从1转移过来

2:从1或者2转移过来

3:从2或者3转移过来

4:从3或者4转移过来

5:从4转移过来

6:从5或者6转移过来

7:从6转移过来

8:从7转移过来

9:从8或者9转移过来

10:从9或者10转移过来

11:从10或者11转移过来 并且这个状态可以更新答案

最麻烦的是从2状态向2状态转移。我们这里用我们正常的坐标,左上角为(1,1)。设转移为(2,k,t)->(2,i,j),其中k<=i<=t+1,j>=t。我们将这个分成两种情况:

(1)i=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];

(2)k<=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]即可。这两个更新的顺序不能反。

int f[2][12][155][155];
int n,m,a[155][555];
 
 
int col;
 
 
int S(int i,int j)
{
    return a[j][col]-a[i-1][col];
}
 
void upMax(int &x,int y)
{
    if(x<y) x=y;
}
 
 
int dp[155][155];
 
 
void clear(int t)
{
    int i,j,k;
    for(i=1;i<12;i++) for(j=0;j<=n+1;j++) for(k=0;k<=n+1;k++) f[t][i][j][k]=-INF;
}
 
 
int main()
{
 
    n=getInt();
    m=getInt();
    int i,j,k;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++) a[i][j]=getInt()+a[i-1][j];
    }
    col=1;
    int pre=0,cur=1;
    clear(pre);
    for(i=1;i<=n;i++) for(j=i;j<=n;j++)
    {
        f[0][1][i][j]=S(i,j);
    }
 
    int ans=-INF;
    for(col=2;col<=m;col++)
    {
        clear(cur);
 
        //1
        for(i=1;i<=n;i++) for(j=i;j<=n;j++)
        {
            upMax(f[cur][1][i][j],f[pre][1][i][j]+S(i,j));
            upMax(f[cur][1][i][j],S(i,j));
        }
 
        //2
        for(i=1;i<=n;i++)
        {
            dp[i][n+1]=-INF;
            for(j=n;j>=i;j--) dp[i][j]=max(dp[i][j+1],f[pre][1][i][j]);
        }
 
        for(i=1;i<=n;i++) for(j=i;j<=n;j++)
        {
            upMax(f[cur][2][i][j],dp[i][j+1]+S(i,j));
        }
 
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) dp[i][j]=-INF;
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) upMax(dp[j+1][j+1],f[pre][2][i][j]);
        for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) upMax(dp[i][j],dp[i][j-1]);
        for(i=1;i<=n;i++) for(j=i;j<=n;j++)
        {
            upMax(f[cur][2][i][j],dp[i][j]+S(i,j));
        }
         
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) dp[i][j]=f[pre][2][i][j];
        for(j=1;j<=n;j++) for(i=1;i<j;i++) upMax(dp[i+1][j],dp[i][j]);
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) upMax(dp[i][j+1],dp[i][j]);  
        for(i=1;i<=n;i++) for(j=i;j<=n;j++)
        {
            upMax(f[cur][2][i][j],dp[i][j]+S(i,j));
        }
 
        //3
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) dp[i][j]=f[pre][2][i][j];
        for(j=1;j<=n;j++) for(i=j;i>=1;i--) upMax(dp[i-1][j],dp[i][j]);
        for(i=1;i<n;i++) for(j=i+1;j<=n;j++)
        {
            upMax(f[cur][3][i][j],dp[i+1][j]+S(i,j));
            upMax(f[cur][3][i][j],f[pre][3][i][j]+S(i,j));
 
        }
 
        //4
        int tmp=f[pre][4][1][1];
 
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) upMax(tmp,f[pre][3][i][j]);
        f[cur][4][1][1]=tmp;
 
        //5
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][5][i][j],f[pre][4][1][1]+S(i,j));
        }
 
        //6
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][6][i][j],f[pre][5][i][j]+S(i,i)+S(j,j));
            upMax(f[cur][6][i][j],f[pre][6][i][j]+S(i,i)+S(j,j));
        }
 
        //7
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][7][i][j],f[pre][6][i][j]+S(i,j));
        }
        //8
        tmp=f[pre][8][1][1];
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) upMax(tmp,f[pre][7][i][j]);
        f[cur][8][1][1]=tmp;
 
        //9
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][9][i][j],f[pre][8][1][1]+S(i,i)+S(j,j));
            upMax(f[cur][9][i][j],f[pre][9][i][j]+S(i,i)+S(j,j));
        }
        //10
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][10][i][j],f[pre][9][i][j]+S(i,j));
            upMax(f[cur][10][i][j],f[pre][10][i][j]+S(i,j));
        }
        //11
        for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(j-i+1>=3)
        {
            upMax(f[cur][11][i][j],f[pre][10][i][j]+S(i,i)+S(j,j));
            upMax(f[cur][11][i][j],f[pre][11][i][j]+S(i,i)+S(j,j));
 
            ans=max(ans,f[cur][11][i][j]);
        }
 
        pre^=1;
        cur^=1;
    }
 
    printf("%d\n",ans);
}

 

转载于:https://www.cnblogs.com/jianglangcaijin/p/4079548.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值