POJ 3349 -- Snowflake Snow Snowflakes

Snowflake Snow Snowflakes
Time Limit: 4000MS   Memory Limit: 65536K
Total Submissions: 45817   Accepted: 11953

Description

You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Your program will read information about a collection of snowflakes, and search for a pair that may be identical. Each snowflake has six arms. For each snowflake, your program will be provided with a measurement of the length of each of the six arms. Any pair of snowflakes which have the same lengths of corresponding arms should be flagged by your program as possibly identical.

Input

The first line of input will contain a single integer n, 0 < n ≤ 100000, the number of snowflakes to follow. This will be followed by n lines, each describing a snowflake. Each snowflake will be described by a line containing six integers (each integer is at least 0 and less than 10000000), the lengths of the arms of the snow ake. The lengths of the arms will be given in order around the snowflake (either clockwise or counterclockwise), but they may begin with any of the six arms. For example, the same snowflake could be described as 1 2 3 4 5 6 or 4 3 2 1 6 5.

Output

If all of the snowflakes are distinct, your program should print the message:
No two snowflakes are alike.
If there is a pair of possibly identical snow akes, your program should print the message:
Twin snowflakes found.

Sample Input

2
1 2 3 4 5 6
4 3 2 1 6 5

Sample Output

Twin snowflakes found.

Source

 
 

题意:

  在n(n<10W)个雪花中判断是否存在两片完全相同的雪花(孪生雪花),每片雪花有6个角,每个角的长度限制为100W

  两片雪花相等的条件:

  雪花6个角的长度按顺序相等(这个顺序即可以是顺时针的也可以是逆时针的)

 

解题思路:

  要判断是否有两个雪花为孪生雪花,首先要明确不能两两比较,10W个雪花两两比较一定会超时

  考虑到如果两个雪花为孪生雪花,那么他们所有的角对应相等,他们所有角的长度之和也一定相等。所以可以首先判断两个雪花的角的长度之和是否相等。可以使用索引表——hash表的方式,为我们的雪花和所有角的长度之和之间建立起映射关系。

  雪花的角的长度最大为100W,所以他们的和最大为600W。经过测试,如果将哈希表的长度设置在600W,其时间复杂度如下图:

  如果将哈希表的长度设置在100W,其时间复杂度如下图:

   可见,并不是哈希表越长,产生冲突的次数越少,越会节省时间,所以我们将哈希表的长度设置为100W(即maxn)

        哈希函数即为:key = 雪花角的长度和 % 1000000

  处理冲突的方法使用链地址法

  当发生冲突时,在使用链地址法寻找当前雪花的插入地址的过程中,与已插入的雪花进行比较。

  比较的方法……首先使用数组存储雪花的六个角的长度,因为有逆时针 顺时针 还不确定起始位置,所以使用循环数组

  上代码吧

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 const __int64 maxn = 1000000;
  6 class
  7 {
  8 public:
  9     __int64 len[6];//六瓣叶子的长度
 10 }snows[100001];
 11 
 12 class HashTable{
 13 public:
 14     __int64 len[6];//六瓣叶子的长度
 15     HashTable *next;//使用链地址法处理冲突
 16     HashTable()//初始化
 17     {
 18         next = 0;
 19     }
 20 };
 21 
 22 HashTable* hashtable[maxn+1];
 23 
 24 ///用于计算hashtable的key值
 25 __int64 computeKey(int k)
 26 {
 27     __int64 key = 0;
 28     for(int i=0;i<6;i++)
 29         key += snows[k].len[i]%maxn;
 30     key = key%maxn;
 31     return ++key;//下标为0的位置我们不使用
 32 }
 33 
 34 bool compare(HashTable *temp,int k)
 35 {
 36     for(int i=0;i<6;i++)
 37     {
 38         //指定len[0]为查找的起点,
 39         //如果有长度为len[0]的花瓣则从这里开始查找,所有花瓣不全相同,则继续查找下一个长度等于len[0]的花瓣
 40         //如果没有长度为len[0]的花瓣,两片雪花肯定不同
 41         if(temp->len[i] == snows[k].len[0])
 42         {///顺时针
 43             if(temp->len[(i+1)%6] == snows[k].len[1]
 44                &&temp->len[(i+2)%6] == snows[k].len[2]
 45                &&temp->len[(i+3)%6] == snows[k].len[3]
 46                &&temp->len[(i+4)%6] == snows[k].len[4]
 47                &&temp->len[(i+5)%6] == snows[k].len[5])
 48                 return true;
 49             ///逆时针
 50             if(temp->len[(i-1+6)%6] == snows[k].len[1]
 51                &&temp->len[(i-2+6)%6] == snows[k].len[2]
 52                &&temp->len[(i-3+6)%6] == snows[k].len[3]
 53                &&temp->len[(i-4+6)%6] == snows[k].len[4]
 54                &&temp->len[(i-5+6)%6] == snows[k].len[5])
 55                 return true;
 56         }
 57     }
 58     return false;//如果两片雪花不一样,返回false
 59 }
 60 
 61 bool Insert(int k)
 62 {
 63     __int64 key = computeKey(k);
 64     if(!hashtable[key])//没有发生冲突
 65     {
 66         HashTable *temp = new HashTable;
 67         for(int i=0;i<6;i++)
 68             temp->len[i] = snows[k].len[i];
 69         hashtable[key] = temp;
 70     }else{//发生地址冲突
 71         HashTable *temp = hashtable[key];
 72         if(compare(temp,k))
 73             return true;
 74         while(temp->next)
 75         {
 76             temp = temp->next;
 77             if(compare(temp,k))
 78                 return true;
 79         }
 80         temp->next = new HashTable;//没有找到孪生雪花,将当前雪花存入hashtable
 81         for(int i=0;i<6;i++)
 82             temp->next->len[i] = snows[k].len[i];
 83     }
 84     return false;//没有找到孪生雪花
 85 }
 86 
 87 int main()
 88 {
 89     int n;
 90     while(cin>>n)
 91     {
 92         memset(hashtable,0,sizeof(hashtable));
 93         bool flag = false;///表示 还没有相同的雪花
 94         for(int i=1;i<=n;i++)
 95         {
 96             for(int j=0;j<6;j++)
 97             {
 98                 scanf("%I64d",&snows[i].len[j]);
 99             }
100             if(!flag)//如果还没有找到孪生雪花,则进行操作
101                 flag = Insert(i);
102         }
103         if(!flag)
104             cout<<"No two snowflakes are alike."<<endl;
105         else
106             cout<<"Twin snowflakes found."<<endl;
107     }
108     return 0;
109 }

 

 

posted @ 2018-02-10 20:48  卉卉卉大爷  阅读(227)  评论(0编辑  收藏  举报