1. 程式人生 > >POJ 3349 -- Snowflake Snow Snowflakes

POJ 3349 -- Snowflake Snow Snowflakes

rem 操作 compare enter script eth measure 時間復雜度 urn

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

CCC 2007

題意:

  在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 }

技術分享圖片

POJ 3349 -- Snowflake Snow Snowflakes