做的第一道哈希表的题目。速度很慢,跑了3000+ms。采用六条边的和对一个大质数的余数作为哈希表的key,理论上质数取得越大,消耗的空间就越大,但是速度会加快,这里取了14997。地址冲突用链表解决。
我认为跑得慢很大一个原因是在比较两篇雪花是否相同的操作相当费时,不知道有没有更好的解决方法。
此外,这个程序还存在的问题是,我写了清除哈希表的函数,但是如果这个函数在程序结束时调用的话,在poj上就会超时,所以就没调用了,其实是钻了空子的。
#include <cstdio>
using namespace std; const int big_prime = ;
const int LEN = ; struct Node{
int len[LEN];
Node *next;
}; Node *hash_table[big_prime + ]; void init_hash_table()
{
for (int i = ; i < big_prime + ; i++){
hash_table[i] = NULL;
}
} void delete_hash_table()
{
for (int i = ; i < big_prime + ; i++){
Node *p = hash_table[i];
while (p){
Node *tmp = p->next;
delete p;
p = tmp;
}
}
} int hash(const Node &node)
{
int key = ;
for (int i = ; i < LEN; i++){
key = (key + node.len[i] ) % big_prime;
}
return key;
} bool cmp(const Node &n1, const Node &n2)
{
for (int start = ; start < LEN; start++){
int j = ;
for (int i = start; j < LEN; j++, i = (i + ) % LEN){
if (n1.len[i] != n2.len[j])
break;
}
if (j == LEN)
return true;
}
for (int start = ; start < LEN; start++){
int j = ;
for (int i = start; j < LEN; j++, i = (i + ) % LEN){
if (n1.len[i] != n2.len[j])
break;
}
if (j == LEN)
return true;
}
return false;
} bool search_and_insert(Node *node)
{
int key = hash(*node);
if (!hash_table[key]){
hash_table[key] = node;
}
else{
Node *p = hash_table[key], *pre = p;
while (p){
if (cmp(*p, *node))
return false;
pre = p;
p = p->next;
}
pre->next = node;
}
return true;
} int main()
{
init_hash_table();
int n;
bool flag = false;
scanf("%d", &n);
for (int i = ; i < n; i++){
int num[LEN];
for (int j = ; j < LEN; j++){
scanf("%d", num + j);
}
if (!flag){
Node *p = new Node;
p->next = NULL;
for (int j = ; j < LEN; j++){
p->len[j] = num[j];
}
if (!search_and_insert(p))
flag = true;
}
}
if (flag){
printf("Twin snowflakes found.\n");
}
else{
printf("No two snowflakes are alike.\n");
}
return ;
}