1. 程式人生 > >AtCoder Regular Contest 062 E - AtCoDeerくんと立方體づくり / Building Cubes with AtCoDeer

AtCoder Regular Contest 062 E - AtCoDeerくんと立方體づくり / Building Cubes with AtCoDeer

tdi space putc sin cst ref ins tps tro

題目傳送門:https://arc062.contest.atcoder.jp/tasks/arc062_c

題目大意:

給你\(N\)塊正方形木板,每塊木板四角有四種顏色(可以相同),木板中央有編號,求選出6塊不同的板子,圍成的本質不同的合法立方體的個數。一個合法立方體,當且僅當木板有編號的一面在外面,且立方體頂點處的三個顏色相同。由於編號的存在,木板可以有4種形態。兩個立方體本質相同,當且僅當存在一種空間旋轉方式,使得兩個立方體一模一樣(包括編號方向)

沒想到這題巨暴力……當我們確定對面的兩塊木板後,整個立方體就確定了……暴力枚舉,然後去重一下就做完了……

/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define inf 0x7f7f7f7f
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
    int x=0,f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline int read(){
    int x=0,f=1; char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=4e2;
int C[N+10][4];
ll v[N+10];
map<ll,int>Mp;
ll Hash(int a,int b,int c,int d){return ((ll)a<<30)|((ll)b<<20)|((ll)c<<10)|(ll)d;}
void Add(ll x,int v){//一種Hash方法
    for (int i=0;i<4;i++,x=(x>>10)|((x&1023)<<30)){
        if (Mp.find(x)==Mp.end())   Mp.insert(map<ll,int>::value_type(x,0));
        Mp.find(x)->Se+=v;
    }
}
int main(){
    int n=read(); ll Ans=0;
    for (int i=1;i<=n;i++){
        for (int j=0;j<4;j++)
            C[i][j]=read();
        v[i]=Hash(C[i][0],C[i][1],C[i][2],C[i][3]);
        Add(v[i],1);
    }
    for (int i=1;i<n-4;i++){
        Add(v[i],-1);
        for (int j=i+1;j<=n;j++){
            Add(v[j],-1);
            for (int k=0;k<4;k++){
                static ll A[4];
                A[0]=Hash(C[i][1],C[i][0],C[j][(k+1)%4],C[j][k    %4]);
                A[1]=Hash(C[i][2],C[i][1],C[j][k    %4],C[j][(k+3)%4]);
                A[2]=Hash(C[i][3],C[i][2],C[j][(k+3)%4],C[j][(k+2)%4]);
                A[3]=Hash(C[i][0],C[i][3],C[j][(k+2)%4],C[j][(k+1)%4]);
                //自己畫圖帶入一下即可
                int a=0,b=0,c=0,d=0;
                map<ll,int>::iterator it;
                if ((it=Mp.find(A[0]))==Mp.end())   continue;
                else    a=it->Se;
                if ((it=Mp.find(A[1]))==Mp.end())   continue;
                else    b=it->Se;
                if ((it=Mp.find(A[2]))==Mp.end())   continue;
                else    c=it->Se;
                if ((it=Mp.find(A[3]))==Mp.end())   continue;
                else    d=it->Se;
                if (!a||!b||!c||!d) continue;
                ll res=1;
                for (int l=0;l<4;l++){
                    res*=Mp.find(A[l])->Se;
                    Add(A[l],-1);
                }
                Ans+=res;
                for (int l=0;l<4;l++)   Add(A[l],1);
            }
            Add(v[j],1);
        }
    }
    printf("%lld\n",Ans);
    return 0;
}

AtCoder Regular Contest 062 E - AtCoDeerくんと立方體づくり / Building Cubes with AtCoDeer