2017.10.12 礼物(zjoi2011) 失败总结

来源:互联网 发布:矩阵式led大灯 编辑:程序博客网 时间:2024/06/05 01:14

听说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 155int 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);} 








原创粉丝点击