终于把省选时的遗憾补上了…
对于构造立方体:
首先BFS构出底层,然后再逐层构造立方体
对于计算:
$O(n^6)$爆搜即可。
#include<cstdio> #include<cstring> const int N=75,M=343010; char ch[N]; int n,m,i,j,k,tmp,q[M],t,l,r; int cnt[M],side[M][6],g[M],loc[M][3],a[N][N][N],ap[N][N][N],ansl=~0U>>1,ansr,sum; int dx[6]={1,-1,0,0,0,0},dy[6]={0,0,1,-1,0,0},dz[6]={0,0,0,0,1,-1}; bool vis[M]; inline void add(int x,int y,int z,int id){vis[q[++t]=a[x][y][z]=id]=1;loc[t][0]=x,loc[t][1]=y,loc[t][2]=z;} inline int getup(int x){for(int i=0;i<cnt[x];i++)if(!vis[side[x][i]])return side[x][i];} inline int getside(int x){for(int i=0;i<cnt[x];i++)if(!vis[side[x][i]]&&cnt[side[x][i]]<5)return side[x][i];} inline int getcommon(int x,int y){for(int i=0;i<cnt[x];i++)if(!vis[side[x][i]])for(int j=0;j<cnt[y];j++)if(side[x][i]==side[y][j])return side[x][i];} void dfs(int u,int d){ int x,y,z,i; for(x=loc[u][0],y=loc[u][1],z=loc[u][2];x&&y&&z&&x<=n&&y<=n&&z<=n;x+=dx[d],y+=dy[d],z+=dz[d])if(!(ap[x][y][z]++))sum+=a[x][y][z]; if(u==t){if(ansl>sum)ansl=sum;if(ansr<sum)ansr=sum;}else for(i=0;i<6;i++)dfs(u+1,i); for(x=loc[u][0],y=loc[u][1],z=loc[u][2];x&&y&&z&&x<=n&&y<=n&&z<=n;x+=dx[d],y+=dy[d],z+=dz[d])if(!(--ap[x][y][z]))sum-=a[x][y][z]; } int main(){ scanf("%d",&n);m=n*n*n; for(i=1;i<=m;i++){ scanf("%d",&g[i]),gets(ch+1),l=1,r=std::strlen(ch+1); while(ch[l]==' ')l++; while(ch[r]==' ')r--;ch[++r]=' '; for(j=l;j<=r;j++)if(ch[j]>='0'&&ch[j]<='9')(side[i][cnt[i]]*=10)+=ch[j]-'0';else cnt[i]++; if(cnt[i]==3)tmp=i; } add(1,1,1,tmp),add(2,1,1,side[tmp][0]),add(1,2,1,side[tmp][1]); for(l=2,r=3;l<r;l=r+1,r=t){ if(loc[l][0]<n)add(loc[l][0]+1,1,1,getside(q[l])); for(i=l;i<r;i++)add(loc[i][0],loc[i][1]+1,1,getcommon(q[i],q[i+1])); if(loc[r][1]<n)add(1,loc[r][1]+1,1,getside(q[r])); } for(k=1;k<n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)add(i,j,k+1,getup(a[i][j][k])); for(t=0,k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++){ a[i][j][k]=g[a[i][j][k]]; if(!a[i][j][k])loc[++t][0]=i,loc[t][1]=j,loc[t][2]=k; } for(i=0;i<6;i++)dfs(1,i); return printf("%d %d",ansl,ansr),0; }