hash表
hash表
Snowflake Snow Snowflakes
有n片雪花,每片雪花有六个角,六个角的角度从顺时针依次记为\(a_1,a_2....a_6\) 判断两片雪花是否相同的依据是 从任何一个角开始顺时针或者逆时针往后记录角度,得到的六元组相等的话,就代表雪花相同,例如\(a_1, a_2...a_6\) 和 \(a_2,a_3...a_1\) 相等的话,两片雪花相同。\(a_1,a_2...a_6\) 和\(a_6,a_5...a_1\) 相等的话,两片雪花相同。
题解:
定义hash函数,H(\(a_1,a_2...a_6\)) = (\(\sum_{i = 1}^{6} a_i + \prod_{i =1}^{6} a_i\)) % mod;(其中mod是我们定义的质数)
建立一个hash表,把n片雪花依次插入,对于每片雪花,我们直接扫描表头H对应的链表,检查是否存在相同的雪花即可。
具体看代码,还是比较简单易懂的
#include <cstdio>
int head[100010], snow[100010][10], next[100010], mod = 99991, cnt;
bool equaln(int *a, int *b) {
for(int i = 0; i < 6; i++) {
int flag = 0;
for(int j = 0; j < 6; j++) {
if(a[(i+j) % 6] != b[j]) {
flag = 1;
break;
}
}
if(!flag) return true;
flag = 0;
for(int j = 5; j >= 0; j--) {
if(a[(i+j) % 6] != b[5-j]) {
flag = 1;
break;
}
}
if(!flag) return true;
}
return false;
}
bool insertn(int *a) {
long long sum = 0, mul = 1, val = 0;
for(int i = 0; i < 6; i++) {
sum = (sum + a[i]) % mod;
mul = (mul * a[i]) % mod;
}
val = (sum + mul) % mod;
for(int i = head[val]; i; i = next[i]) {
if(equaln(snow[i], a)) return true;
}
cnt++;
for(int i = 0; i < 6; i++) {
snow[cnt][i] = a[i];
}
next[cnt] = head[val];
head[val] = cnt;
return false;
}
int main() {
int n, f = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
int a[10];
for(int j = 0; j < 6; j++) {
scanf("%d", &a[j]);
}
if(insertn(a)) {
f = 1;
}
}
if(f == 1) printf("Twin snowflakes found.\n");
else printf("No two snowflakes are alike.\n");
return 0;
}