POJ 3349 Snowflake Snow Snowflakes

题目跳转:POJ 3349

Describe:
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.

题目大意:

给n多雪花,判断有无两片雪花是相同的,用六个正整数(代表雪花六个边的长度)来描述每一片雪花,并且,六个整数可以以任一起点以顺或逆时针旋转,就是说1 2 3 4 5 6这片雪花和3 4 5 6 1 2是同一片(顺时针) 和4 3 2 1 6 5也是同一片(逆时针)。

解题思路:

题目数据比较大,暴力的话会T,所以可以减少比较次数,即哈希值相同的再作比较,哈希函数选用相加取余,复杂度低,用链地址法解决冲突。比较的话,就是既比较顺时针,如果不相同,再比较逆时针,同时枚举起点。

AC代码:

 

 1 #include 
 2 #include 
 3 #include  // 用来动态分配内存的头文件
 4 #define N 100010 // 数据范围
 5 #define M 14997 // 用作哈希函数的求余的质数,据dalao说质数越大消耗内存越大
 6 using namespace std;
 7 typedef struct Node
 8 {
 9     int a[6];
10     struct Node *next; // 第一次用的数组,后来因为MLE,所以用的指针
11 } node;
12 node s[4*N]; // 开的大一点,之前交的时候RE了,可能是开太小了
13 int istrue(int a[], int b[]) // 这个就是顺时针判断,和逆时针判断,通过枚举起点的方法
14 {
15     for(int i = 0; i < 6; i++) // 顺时针
16     {
17         int f = 1;
18         for(int j = 0,k = i; j < 6; j++,k=(k+1)%6)
19         {
20             if(a[j] != b[k])
21             {
22                 f = 0;
23                 break;
24             }
25         }
26         if(f == 1) return 1;
27     }
28     for(int i = 0; i < 6; i++) // 逆时针
29     {
30         int f = 1;
31         for(int j = 0,k = i; j < 6; j++,k=((k-1)<0?5:(k-1))%6)
32         {
33             if(a[j] != b[k])
34             {
35                 f = 0;
36                 break;
37             }
38         }
39         if(f == 1) return 1;
40     }
41     return 0;
42 }
43 void init() // 结构数组初始化
44 {
45     for(int i = 0; i < 4*N; i++)
46     {
47         s[i].next = NULL;
48     }
49 }
50 int main()
51 {
52     init();
53     int n;
54     scanf("%d",&n);
55     int b[6], sum, f = 0; // b数组用作中间变量,sum求和用作hash函数,f是结果标志
56     while(n--)
57     {
58         sum = 0; // sum初始化
59         for(int i = 0; i < 6; i++)
60         {
61             scanf("%d",&b[i]);
62             sum += b[i]%M;  // 求余的定理,防止溢出
63         }
64         if(f == 0) // 如果已经发现两个一样的雪花了,后面的事情就不用做了
65         {
66             sum = sum%M;
67             if(s[sum].next == NULL) // 该数组还没有值
68             {
69                 for(int i = 0; i < 6; i++)
70                     s[sum].a[i] = b[i];
71                 node *temp = (node*)malloc(sizeof(node)); // 为后面的申请一块空间
72                 temp->next = NULL;
73                 s[sum].next = temp;
74             } else { // 若已经有雪花了,则插入同时作比较
75                 node *tmp = &s[sum];
76                 do
77                 {
78                     if(istrue(tmp->a,b) == 1)
79                         f = 1;
80                     tmp = tmp->next;
81                 }while(tmp != NULL && f == 0);
82                 if(f == 0) // 不一样的话,就插入并申请空间
83                 {
84                     tmp = &s[sum];
85                     while(tmp->next != NULL) tmp = tmp->next;
86                     for(int i = 0; i < 6; i++)
87                         tmp->a[i] = b[i];
88                     node *temp = (node*)malloc(sizeof(node));
89                     temp->next = NULL;
90                     tmp->next = temp;
91                 }
92             }
93         }
94     }
95     if(f == 1) printf("Twin snowflakes found.\n"); // 按要求打印答案
96     else printf("No two snowflakes are alike.\n");
97     return 0;
98 }
View Code

 

(代码有点多,折叠了)

 

小结:链址法应开一个指针,第一次开数组结果MLE了,开指针可以节省一些空间。

你可能感兴趣的:(POJ 3349 Snowflake Snow Snowflakes)