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
。
时间限制:
2s
空间限制:
512MB
分析
很自然地分成
9
个部分进行动态规划,即把NOI3个字母,每个字母分别从左到右分为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年卡可用
立即使用
06-17
186
01-05
3555
08-10
819
06-21
1367
09-03
327
11-06
118
04-29
1217
03-10
289
05-23
148
02-13
144
02-13
122
07-29
119
05-02
261
传送门
注意到\(N\ O\ I\)三个字母都可以从左到右拆成三部分,即\(N=\)一个矩形+一堆矩形+一个矩形,\(O=\)一条+两条横的+一条,\(I=\)两条横的+一个矩形+两条横的,所以可以拆成\(13\)个部分转移(\(9\)个字母部分,\(4\)个空白部分)
设\(f_{i,j,l,r}\)表示第\(i\)列,放的是字母的\(j\)部分,放了从\(l\)行到\(r\)行的最大值,\(g...
11-04
499
04-03
381
09-07
496
07-25
365
成就一亿技术人!
|