【arc062e】Building Cubes with AtCoDeer

Description

STL有n块瓷砖,编号从1到n,并且将这个编号写在瓷砖的正中央;

瓷砖的四个角上分别有四种颜色(可能相等可能不相等),并且用Ci,0,Ci,1,Ci,2,Ci,3分别表示左上、右上、右下、左下的颜色。颜色有1000种,编号从0到999。

现在STL想知道,从这n块瓷砖中选出不同的6块,能围成多少本质不同的合法的立方体。

一个立方体被称为合法的,当且仅当瓷砖有编号的一侧在外面,并且立方体的每个顶点处的三个颜色相同。

注意,由于瓷砖的中间是写着编号的,因此将一个瓷砖旋转90度之后,这个瓷砖会发生变化,也就是说一块瓷砖可以被用作四个方向(哪怕旋转后四个角的颜色对应相等)。

两个立方体被称作是本质相同的,当且仅当存在在空间中旋转一个立方体的方式,使其和第二个立方体一模一样(包括每面瓷砖上编号的方向)。


Solution

n最大为400,显然可以暴力解决。

我们可以发现,当一个立方体中,只要确定了任意两个相对的面,就可唯一确定整个立方体。

因此我们枚举相对两面编号及编号方向,用map储存瓷砖,计算方案即可。

ps:由于正方形可旋转,因此存入map时,要将旋转4次的结果都存入map中。

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<map>
 5 using namespace std;
 6 #define hash func
 7 typedef long long ll;
 8 int n,c[410][4];
 9 ll ans=0,h[410];
10 map<ll,int>mp;
11 ll hash(ll a,ll b,ll c,ll d){
12     return a<<30|b<<20|c<<10|d;
13 }
14 void add(ll x,int k){
15     for(int i=4;i;x=x>>10|(x&1023)<<30,i--)
16         mp[x]+=k;
17     return;
18 }
19 int main(){
20     mp.clear();
21     scanf("%d",&n);
22     for(int i=1;i<=n;i++){
23         scanf("%d%d%d%d",c[i]+0,c[i]+1,c[i]+2,c[i]+3);
24         h[i]=hash(c[i][0],c[i][1],c[i][2],c[i][3]);
25         add(h[i],1);
26     }
27     for(int i=1;i<n-4;i++){
28         add(h[i],-1);
29         for(int j=i+1;j<=n;j++){
30             add(h[j],-1);
31             for(int k=0;k<4;k++){
32                 ll a[4];
33                 a[0]=hash(c[i][3],c[i][2],c[j][(k+1)%4],c[j][k]);
34                 a[1]=hash(c[i][2],c[i][1],c[j][(k+2)%4],c[j][(k+1)%4]);
35                 a[2]=hash(c[i][1],c[i][0],c[j][(k+3)%4],c[j][(k+2)%4]);
36                 a[3]=hash(c[i][0],c[i][3],c[j][k],c[j][(k+3)%4]);
37                 if(mp[a[0]]==0||mp[a[1]]==0||mp[a[2]]==0||mp[a[3]]==0)
38                     continue;
39                 ll res=1;
40                 for(int l=0;l<4;l++){
41                     res*=mp[a[l]];
42                     add(a[l],-1);
43                 }
44                 ans+=res;
45                 for(int l=0;l<4;l++)
46                     add(a[l],1);
47             }
48             add(h[j],1);
49         }
50     }
51     printf("%lld\n",ans);
52     return 0;
53 }
posted @ 2018-08-23 20:10  乖巧的小团子QwQ  阅读(334)  评论(0编辑  收藏  举报