听说n^4能过,于是愉快地敲了n^4 ,还带了两个最优性剪枝。。
结果事实证明是别人家的n^4.。。(wys?)
很奇怪玄学剪枝有时2^50次方都能过,为什么这个连1e10都过不了。.。
TLE代码:
#include<iostream>
#include<cstdio>
using namespace std;
int x,y,z,xx[155][155][155],yy[155][155][155],zz[155][155][155],i,j,k,lin[155],a,qi,tu[155][155][155],ans;
char ch;
int main()
{
scanf("%d%d%d",&y,&x,&z);
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
for(k=1;k<=z;k++)
{
scanf("%c",&ch);
while(ch!='N'&&ch!='P')scanf("%c",&ch);
if(ch=='N')tu[i][j][k]=1;
else tu[i][j][k]=0;
}
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
{
for(k=1;k<=z;k++)
{
lin[k]=lin[k-1]+tu[i][j][k];
xx[i][j][k]=xx[i][j-1][k]+lin[k];
}
}
for(i=1;i<=y;i++)
for(j=1;j<=x;j++)
{
for(k=1;k<=z;k++)
{
lin[k]=lin[k-1]+tu[j][i][k];
yy[i][j][k]=yy[i][j-1][k]+lin[k];
}
}
for(i=1;i<=z;i++)
for(j=1;j<=x;j++)
{
for(k=1;k<=y;k++)
{
lin[k]=lin[k-1]+tu[j][k][i];
zz[i][j][k]=zz[i][j-1][k]+lin[k];
}
}
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
for(a=min(x-i,y-j);a>=0;a--)
{ if(4*(a+1)*z<=ans)break;
qi=0;
for(k=1;k<=z;k++)
{
if(4*(z-qi+1)*(a+1)<=ans)break;
if(zz[k][i+a][j+a]-zz[k][i-1][j+a]-zz[k][i+a][j-1]+zz[k][i-1][j-1]==(a+1)*(a+1))
{
ans=max(ans,4*(a+1)*(k-qi));
}else qi=k;
}
}
for(i=1;i<=y;i++)
for(j=1;j<=z;j++)
for(a=min(y-i,z-j);a>=0;a--)
{ if(4*(a+1)*x<=ans)break;
qi=0;
for(k=1;k<=x;k++)
{
if(4*(x-qi+1)*(a+1)<=ans)break;
if(xx[k][i+a][j+a]-xx[k][i-1][j+a]-xx[k][i+a][j-1]+xx[k][i-1][j-1]==(a+1)*(a+1))
{
ans=max(ans,4*(a+1)*(k-qi));
}else qi=k;
}
}
for(i=1;i<=x;i++)
for(j=1;j<=z;j++)
for(a=min(x-i,z-j);a>=0;a--)
{
if(4*(a+1)*y<=ans)break;
qi=0;
for(k=1;k<=y;k++)
{
if(4*(y-qi+1)*(a+1)<=ans)break;
if(xx[k][i+a][j+a]-xx[k][i-1][j+a]-xx[k][i+a][j-1]+xx[k][i-1][j-1]==(a+1)*(a+1))
{
ans=max(ans,4*(a+1)*(k-qi));
}else qi=k;
}
}
printf("%d",ans);
}
正解是单调栈。。
首先先选一个为底面, 把 他分成好几层 然后再枚举矩形右下角坐标,,这时候暴力的做法就是枚举正方形大小,然而这样做忽略了
整体满足,部分也满足 的性质。所以对于一个正方形,若以n为边长合适,则以1~n为边长也一定合适
所以就在这一个线所在点的矩形最大的n都考虑进来,就相当于
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 155
int k,i,j,zuo[N],you[N],f[N][N][N],sta[N],top,ans,x,y,z;
char tu[N][N][N],tu2[N][N][N];
void work(int z,int x,int y)
{
for(k=1;k<=z;k++)
{
for(i=1;i<=x;i++)
{
for(j=1;j<=y;j++)
{
if(tu[i][j][k]=='N')f[k][i][j]=min(f[k][i-1][j-1],min(f[k][i-1][j],f[k][i][j-1]))+1;
else f[k][i][j]=0;
}
}
}
for(j=1;j<=x;j++)
for(k=1;k<=y;k++)
{
memset(zuo,0,sizeof(zuo));
top=0;
sta[0]=0;
for(i=1;i<=z;i++)
{
while(top&&f[sta[top]][j][k]>=f[i][j][k])--top;
zuo[i]=i-sta[top];
sta[++top]=i;
}
memset(you,0,sizeof(you));
top=0;
sta[0]=z+1;
for(i=z;i>=1;i--)
{
while(top&&f[sta[top]][j][k]>=f[i][j][k])--top;
you[i]=sta[top]-i;
sta[++top]=i;
}
for(i=1;i<=z;i++)
if(tu[j][k][i]=='N')ans=max(ans,(zuo[i]+you[i]-1)*4*f[i][j][k]);
}
}
int main()
{
scanf("%d%d%d",&y,&x,&z);
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
for(k=1;k<=z;k++)
{
scanf("%c",&tu[i][j][k]);
while(tu[i][j][k]!='N'&&tu[i][j][k]!='P')scanf("%c",&tu[i][j][k]);
tu2[i][j][k]=tu[i][j][k];
}
work(z,x,y);
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
for(k=1;k<=z;k++)
{
tu[j][k][i]=tu2[i][j][k];
}
work(x,y,z);
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
for(k=1;k<=z;k++)
{
tu[i][k][j]=tu2[i][j][k];
}
work(y,x,z);
printf("%d",ans);
}