P3335 [ZJOI2013]蚂蚁寻路
Forever丶CIL · · 题解
P3335 这个题思维难度还是有的。。(至少我是这么想的。。大佬就别吐槽我了)
首先,通过题目描述,我们可以在纸上画一画,可以发现,图像一定是像长城一样的
就是好多个矩形它们的底在一条直线上,高和宽不同,而且,还有一点就是它是高低相间的
而且由右转形成高峰,由左转形成低谷。
那么我们可以枚举图的右下角(i,j),那么有两种情况:
一:第j-1列和第j列在同一个矩形里;
二:第j-1列和第j列在不同的矩形里;
我们要记录的状态与点(i,j),p(指的是当前枚举的是第p个矩形),h(当前枚举的举行高度为i-h+1)有关
对于一情况:令f[i][j][p][h]来表示前i行前j列,到第p个矩形,且第p个矩形高为i-h+1时的最优解。 则 f[i][j][p][h]=f[i][j-1][p][h]+s[i][j]-s[h-1][j];
(这里这个s数组求的是每一列的前缀和,可以在输入中预处理出来,方便计算用)
对于二情况:再分两种讨论,如果第p个矩形比第p-1个矩形高,则应从f[i][j-1][p-1][高度小于i-h+1]中找一个 max来转移,如果第p个矩形比第p-1个矩形矮,则应从f[i][j-1][p-1][高度大于i-h+1]中找一个max来转移。 因为一个个枚举高度大于i-h+1和小于i-h+1太浪费时间了,所以我们再开一个数组g[i][j][p][h][0/1]来表示 高度比i-h+1高的/矮的之中,f数组中的max。
我这里直接用f[i][j-1][p-1][高度大于i-h+1]这样的方式讲解了,但其实f数组最后一维的h并不是第p个矩形的高度,而是这样的:i是矩形的最下面一行,h则是最上面一行,所以i-h+1才是高度。
根据分析,转移就好写了:
f[i][j][p][h]=max(f[i][j-1][p][h],g[i][j-1][p-1][h][p%2])+s[i][j]-s[h-1][j];
关于g数组的维护,因为我们已经维护出f数组的第j列了
那么这一列所在的矩形要么是低谷,要么是高峰,我们都要考虑
->高峰:
g[i][j][p][h][0]=max(f[i][j][p][h-1],g[i][j][p][h-1][0]);
->低谷:
g[i][j][p][h][1]=max(f[i][j][p][h+1],g[i][j][p][h+1][1]);
当然我们可以在计算过程中更新答案,还可以省掉i这一维
因为从方程中就可以看出来i其实没有参与转移
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=120;
const int Inf=1000000001;
int n,m,k,ans;
int a[maxn][maxn];
int f[maxn][25][maxn];
int g[maxn][25][maxn][2];
int s[maxn][maxn];
void ini()
{
scanf("%d%d%d",&n,&m,&k);
k=k*2+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]); s[i][j]=s[i-1][j]+a[i][j];
for(int p=1;p<=k;p++)
for(int h=1;h<=n;h++)
f[0][p][h]=-Inf,g[0][p][h][0]=-Inf,g[0][p][h][1]=-Inf;
}
void dp()
{
ans=-Inf;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int p=1;p<=k;p++)
{
for(int h=i;h>=1;h--)
f[j][p][h]=max(f[j-1][p][h],g[j-1][p-1][h][p%2])+s[i][j]-s[h-1][j];
g[j][p][1][0]=-Inf;
for(int h=2;h<=i;h++) g[j][p][h][0]=max(f[j][p][h-1],g[j][p][h-1][0]);
g[j][p][i][1]=-Inf;
for(int h=i-1;h>=1;h--) g[j][p][h][1]=max(f[j][p][h+1],g[j][p][h+1][1]);
}
ans=max(ans,max(f[j][k][i],g[j][k][i][0]));
}
}
}
int main()
{
ini();
dp();
printf("%d\n",ans);
return 0;
}
大家也会发现,g数组的最后一维也能省掉,因为对于特定的p,它是高峰还是低谷是确定的。
rp++