POJ_3349_Snowflake Snow Snowflakes(哈希表)
http://poj.org/problem?id=3349
/*
题意:输入n个雪花,判断这些雪花中是否有两片是一样的,包括顺时针判断和逆时针判断
如果输入过程发现已经有一样的了还得继续输入。
使用哈希就是为了减少比较的次数,即只有当哈希地址相同的时候才比较,因为哈希地址不同
说明两片雪花肯定是不一样的。
在这里主要是解决哈希地址冲突的问题,此处是用的链式存储。
1:计算哈希地址的时候用的是连加取余法;为了避免产生大数,使用了同余模定理:
(a+b+c)%r=(a%r+b%r+c%r)%r;
2:在顺时针逆时针判断是否一样的时候使用了取余。
*/
1 /* 2 题意:输入n个雪花,判断这些雪花中是否有两片是一样的,包括顺时针判断和逆时针判断 3 如果输入过程发现已经有一样的了还得继续输入。 4 使用哈希就是为了减少比较的次数,即只有当哈希地址相同的时候才比较,因为哈希地址不同 5 说明两片雪花肯定是不一样的。 6 在这里主要是解决哈希地址冲突的问题,此处是用的链式存储。 7 1:计算哈希地址的时候用的是连加取余法;为了避免产生大数,使用了同余模定理: 8 (a+b+c)%r=(a%r+b%r+c%r)%r; 9 2:在顺时针逆时针判断是否一样的时候使用了取余。 10 */ 11 # include <stdio.h> 12 # include <string.h> 13 #include<iostream> 14 using namespace std; 15 const __int64 prime=999983; //100w内的最大素数 16 struct node 17 { 18 __int64 len[6]; 19 }leaf[100001]; //存储输入的叶子。 20 typedef struct HashTable 21 { 22 __int64 len[6]; //6瓣叶子的长度 23 HashTable *next; //用于冲突的时候开放地址。 24 HashTable() //Initial;也可以在申请空间的时候初始化。但是如果加上下面的 25 //申请空间的时候不用初始化。 26 { 27 next=0; 28 } 29 }Hashtable; 30 Hashtable *hash[prime+1]; //指针数组,数组元素是指向Hashtable的指针; 31 __int64 compute_key(int k) //计算哈希地址; 32 { 33 __int64 key=0; 34 for(int i=0;i<6;i++) 35 { 36 key+=(leaf[k].len[i]) % prime; 37 key%=prime; 38 } 39 return key++; 40 } 41 bool clockwise(Hashtable *p,int k) //顺时针判断 42 { 43 for(int j=0;j<6;j++) 44 { 45 bool flag=true; 46 for(int i=0;i<6;i++) 47 if(leaf[k].len[i] != p->len[(i+j)%6]) 48 { 49 flag=false; //有一片不相同剩余的就不用判断了。 50 break; 51 } 52 if(flag) //一个循环下来相同直接返回true 53 return true; 54 } 55 return false; 56 } 57 bool counterclockwise(Hashtable *p,int k) //逆时针判断。 58 { 59 for(int j=0;j<6;j++) 60 { 61 bool flag=true; 62 for(int i=0;i<6;i++) 63 if(leaf[k].len[i] != p->len[(12-i-j)%6]) 64 { 65 flag=false; 66 break; 67 } 68 if(flag) 69 return true; 70 } 71 return false; 72 } 73 bool insert(int k) 74 { 75 __int64 key=compute_key(k); //得到哈希地址。 76 77 if(!hash[key]) //如果不冲突也就是这个地址没有存数据, 78 { 79 Hashtable* temp=new Hashtable; //申请空间 80 // temp->next=0; 81 for(int i=0;i<6;i++) 82 temp->len[i]=leaf[k].len[i]; 83 84 hash[key]=temp; //保存数值 85 } 86 else //地址冲突,那么开放地址,顺便比较是否雪花相同 87 { 88 Hashtable *temp=hash[key]; //临时存放原来哈希地址存的数据。 89 // temp->next=0; 90 if(clockwise(temp,k) || counterclockwise(temp,k)) //检查雪花是否相同 91 return true; 92 while(temp->next) 93 { 94 temp=temp->next; 95 if(clockwise(temp,k) || counterclockwise(temp,k)) //检查雪花是否相同 96 return true; 97 } 98 //如果在hash冲突的数据中还没有相同的 99 temp->next=new Hashtable; //开辟新空间存放数据 100 //temp->next->next=0; 101 for(int i=0;i<6;i++) 102 temp->next->len[i]=leaf[k].len[i]; 103 } 104 return false; 105 } 106 107 int main() 108 { 109 int n,i,j; 110 while(scanf("%d",&n) != EOF) 111 { 112 memset(hash,0,sizeof(hash)); 113 bool flag=false; 114 for(i=1;i<=n;i++) 115 { 116 for(j=0;j<6;j++) 117 scanf("%I64d",&leaf[i].len[j]); 118 if(!flag) 119 flag=insert(i); 120 } 121 if(flag) 122 printf("Twin snowflakes found.\n"); 123 else 124 printf("No two snowflakes are alike.\n"); 125 126 127 } 128 return 0; 129 }