标签:namespace 冲突 元组 比较 数据 另一个 i++ 顺序 sum
# 题意
有n片雪花,每片雪花有6个角,每个角都有长度,
定义两片雪花同构当且仅当两片雪花分别从某一个点开始,
顺时针或者逆时针后点对应相等即为形状相同的雪花,
问这n片雪花中是否存在两片形状相同的雪花
# 题解
hash函数取六个点的和 与 六个点的积 的和 这样就能保证6个点的数值一定有某种顺序对应相等
判断两个6元组是否相等就枚举两个的起始点即可,只需要其中一个顺序,分别比较另一个的顺序和逆序比较即可
每次插入都与hash值相同的进行比较如果比较成功可以直接结束,否则依次比较当所有都插入并且没有相等的
对于随机数据,期望的时间复杂度为O(N* N/P),取P为最接近N的质数,冲突的概率小,时间复杂度可以有效降低
期望的时间复杂度为O(N)
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int N=1e5+10,P=99991;
4 int sonw[N][6],h[N],ne[N],idx;
5 inline int H(int *a){
6 int sum=0,mul=1;
7 for (int i = 0; i <6 ; ++i) {
8 sum=(sum+a[i])%P;
9 mul=(long long)mul*a[i]%P;
10 }
11 return (sum+mul)%P;
12 }
13 inline bool equal(int *a,int *b)
14 //两个图形分别从每个点开始、分别逆时、顺时,若都不相同则形状不同否则相同
15 {
16 for (int i = 0; i <6 ; ++i)
17 for (int j = 0; j <6 ; ++j) {
18 bool eq=1;
19 for (int k = 0; k <6 ; ++k) {
20 if( a[(i+k)%6] != b[(j+k)%6] ) eq=0;
21 }
22 if(eq) return 1;
23 eq=1;
24 for (int k = 0; k <6 ; ++k) {
25 if( a[(i+k)%6] != b[(j-k+6)%6] ) eq=0;
26 }
27 if(eq) return 1;
28 }
29 return 0;
30 }
31 inline bool insert(int *a){
32 int val=H(a);
33 for (int i = h[val]; i ; i=ne[i]) {
34 if(equal(sonw[i],a))
35 return 1;
36 }
37 ++idx;
38 memcpy(sonw[idx],a,6*sizeof(int));
39 ne[idx]=h[val];
40 h[val]=idx;
41 return 0;
42 }
43 int main() {
44 ios::sync_with_stdio(0);
45 cin.tie(0);
46 cout.tie(0);
47 int n;
48 cin>>n;
49 for(int i=1;i<=n;i++)
50 {
51 int a[10];
52 for (int i = 0; i <6 ; ++i)
53 cin>>a[i];
54
55 if(insert(a))
56 {
57 puts("Twin snowflakes found.");
58 return 0;
59 }
60 }
61 puts("No two snowflakes are alike.");
62 }
标签:namespace 冲突 元组 比较 数据 另一个 i++ 顺序 sum
原文地址:https://www.cnblogs.com/hhyx/p/12495730.html