实际上,可以不用建水晶立方体...
因为,发光水晶的方向都要枚举一遍。
只需知道发光水晶每个方向有哪些水晶就可以了。
对于一个发光水晶,将它连接的水晶标号。
从该水晶bfs,若某水晶在相同步数下被访问过两次,那么它必然不是某一方向的直线上的(挺显然的吧)。
每个点的标号为最先访问到它的点的标号。
这样可以整出发光水晶每个方向的水晶。
时间复杂度\(o(n a^3)\)。
之后把每个发光水晶朝向枚举一遍,复杂度\(o(6^n a)\)。
#include#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)#define mem(a,b) memset(a,b,sizeof a )#define debug(a) cerr<<#a<<' '< <<"___"< 47);}const int mn=70*70*70+100;int n;vector son[mn];vector rt,ft[8][6];int mk[mn];int val[mn],que[mn],mark[mn];bool is_used[mn];int tot_val,Max,Min=1e9;void dfs(int x){ if(x==(int)rt.size()){ Max=max(Max,tot_val); Min=min(Min,tot_val); return; } vector sta; rep(q,0,5){ sta.clear(); rep(w,0,(int)ft[x][q].size()-1){ int y=ft[x][q][w]; if(!is_used[y]){ sta.push_back(y); is_used[y]=1; tot_val+=val[y]; } } dfs(x+1); rep(w,0,(int)sta.size()-1)is_used[sta[w]]=0,tot_val-=val[sta[w]]; if(ft[x][q].size()==0)return; }}int main(){ freopen("glitter.in","r",stdin); freopen("glitter.out","w",stdout); in(n); char c; int r; rep(q,1,n*n*n){ in(val[q]); if(!val[q])rt.push_back(q); while(1){ r=0; while(c=getchar(),c<48); do r=(r<<1)+(r<<3)+(c^48); while(c=getchar(),c>47); son[q].push_back(r); if(c=='\n'||c=='\r')break; } } rep(q,0,(int)rt.size()-1){ int l=0,r=0; int now=rt[q]; mk[now]=-1; rep(w,0,(int)son[now].size()-1)mk[son[now][w]]=w+1,mark[son[now][w]]=1,que[++r]=son[now][w]; while(l