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 }

 

posted on 2013-08-20 16:41  随风浪子的博客  阅读(125)  评论(0编辑  收藏  举报

导航