1 = 3
= 12
[ − 50 , 50 ]
2345
≤ 10
≤ 20
[ − 50 , 50 ]
6789
≤ 150
≤ 500
= 1
1011
≤ 80
≤ 80
[ − 200 , 200 ]
12131415
≤ 150
≤ 500
[ − 200 , 200 ]
1617181920
对于所有的测试数据,保证
n ≥ 3 , m ≥ 12
。
时间限制:
2 s
空间限制:
512 MB
分析
很自然地分成
9
个部分进行动态规划,即把N O I 3个字母,每个字母分别从左到右分为3部分,然后逐列进行转移。 除了
N
<script type="math/tex" id="MathJax-Element-1892">N</script>的第二部分其余的都很好转移,具体怎么转移的呢?其实也就是按照他的规则进行模拟,看代码就能理解了。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std ;
#define MAXN 150
#define MAXM 500
#define INF 0x3fffffff
int a[MAXN+10 ][MAXM+10 ],n,m,blk[MAXM+10 ][2 ],f[2 ][10 ][MAXN+10 ][MAXN+10 ],s[MAXN+10 ][MAXM+10 ],tmp[MAXN+10 ][MAXN+10 ],ans=-INF;
void Read(int &x){
static char c;
bool f(0 );
while (c=getchar(),c!=EOF){
if (c=='-' )
f=1 ;
else if (c>='0' &&c<='9' ){
x=c-'0' ;
while (c=getchar(),c>='0' &&c<='9' )
x=x*10 +c-'0' ;
ungetc(c,stdin);
if (f)
x=-x;
return ;
}
}
}
void read(){
Read(n),Read(m);
int i,j;
for (i=1 ;i<=n;i++)
for (j=1 ;j<=m;j++){
Read(a[i][j]);
s[i][j]=s[i-1 ][j]+a[i][j];
}
}
void dp(){
int i,j,k;
memset (f[1 ],0xb0 ,sizeof f[1 ]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
f[1 ][1 ][i][j]=s[j][1 ]-s[i-1 ][1 ];
blk[1 ][0 ]=blk[1 ][1 ]=-INF;
for (k=2 ;k<=m;k++){
memset (f[k&1 ],0xb0 ,sizeof f[k&1 ]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
f[k&1 ][1 ][i][j]=max(s[j][k]-s[i-1 ][k],f[(k&1 )^1 ][1 ][i][j]+s[j][k]-s[i-1 ][k]);
for (i=1 ;i<=n;i++){
tmp[i][n+1 ]=-INF;
for (j=n;j>=i;j--)
tmp[i][j]=max(tmp[i][j+1 ],f[(k&1 )^1 ][1 ][i][j]);
}
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++){
f[k&1 ][2 ][i][j]=max(f[k&1 ][2 ][i][j],tmp[i][j+1 ]+s[j][k]-s[i-1 ][k]);
tmp[i][j]=-INF;
}
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
tmp[j+1 ][j+1 ]=max(tmp[j+1 ][j+1 ],f[(k&1 )^1 ][2 ][i][j]);
for (i=1 ;i<=n;i++)
for (j=i+1 ;j<=n;j++)
tmp[i][j]=max(tmp[i][j],tmp[i][j-1 ]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
f[k&1 ][2 ][i][j]=max(f[k&1 ][2 ][i][j],tmp[i][j]+s[j][k]-s[i-1 ][k]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
tmp[i][j]=f[(k&1 )^1 ][2 ][i][j];
for (j=1 ;j<=n;j++)
for (i=1 ;i<j;i++)
tmp[i+1 ][j]=max(tmp[i+1 ][j],tmp[i][j]);
for (i=1 ;i<=n;i++)
for (j=i;j<n;j++)
tmp[i][j+1 ]=max(tmp[i][j+1 ],tmp[i][j]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
f[k&1 ][2 ][i][j]=max(f[k&1 ][2 ][i][j],tmp[i][j]+s[j][k]-s[i-1 ][k]);
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
tmp[i][j]=f[(k&1 )^1 ][2 ][i][j];
for (j=1 ;j<=n;j++)
for (i=j;i>1 ;i--)
tmp[i-1 ][j]=max(tmp[i-1 ][j],tmp[i][j]);
for (i=1 ;i<=n;i++)
for (j=i+1 ;j<=n;j++)
f[k&1 ][3 ][i][j]=max(f[k&1 ][3 ][i][j],max(tmp[i+1 ][j],f[(k&1 )^1 ][3 ][i][j])+s[j][k]-s[i-1 ][k]);
blk[k][0 ]=blk[k-1 ][0 ];
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
blk[k][0 ]=max(blk[k][0 ],f[(k&1 )^1 ][3 ][i][j]);
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++)
f[k&1 ][4 ][i][j]=blk[k-1 ][0 ]+s[j][k]-s[i-1 ][k];
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++)
f[k&1 ][5 ][i][j]=max(f[(k&1 )^1 ][4 ][i][j],f[(k&1 )^1 ][5 ][i][j])+a[i][k]+a[j][k];
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++)
f[k&1 ][6 ][i][j]=f[(k&1 )^1 ][5 ][i][j]+s[j][k]-s[i-1 ][k];
blk[k][1 ]=blk[k-1 ][1 ];
for (i=1 ;i<=n;i++)
for (j=i;j<=n;j++)
blk[k][1 ]=max(blk[k][1 ],f[(k&1 )^1 ][6 ][i][j]);
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++)
f[k&1 ][7 ][i][j]=max(blk[k-1 ][1 ],f[(k&1 )^1 ][7 ][i][j])+a[i][k]+a[j][k];
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++)
f[k&1 ][8 ][i][j]=max(f[(k&1 )^1 ][7 ][i][j],f[(k&1 )^1 ][8 ][i][j])+s[j][k]-s[i-1 ][k];
for (i=1 ;i<=n;i++)
for (j=i+2 ;j<=n;j++){
f[k&1 ][9 ][i][j]=max(f[(k&1 )^1 ][8 ][i][j],f[(k&1 )^1 ][9 ][i][j])+a[i][k]+a[j][k];
ans=max(ans,f[k&1 ][9 ][i][j]);
}
}
}
int main()
{
read();
dp();
printf ("%d\n" ,ans);
}
确定要放弃本次机会?
福利倒计时
:
:
立减 ¥
普通VIP年卡可用
立即使用
04-03
291
3553
积分
108
粉丝
75
获赞
61
评论
52
收藏
分类专栏
成就一亿技术人!