题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=130
解题思路:对于每种边长的输入,将边长和作为Hash值,使用静态链表next(结构体数组)处理冲突。将所有可能的边长顺序存储在next链表中。当有新元素插入静态链表时采用从头插入的方式插入新的边长序列。
对于一组边长序列,使用循环左移和循环右移的方式求的虽有可能的边长顺序序列:
假如输入的边长序列是1 2 3 4 5 6,设置两个长度是10的序列。其中一个存储1 2 3 4 5 6 1 2 3 4 5,从左到右每六个读取,相当于实现了循环左移;另一个存储6 5 4 3 2 1 6 5 4 3 2,从左到右每六个读取,相当于实现了循环右移。每次生成一个新的序列顺序,将其添加到next静态链表中。
代码如下:
- #include <iostream>
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- const int N = 1200010;
- const int H = 1200007;
- struct Node
- {
- int num[6];
- int next;
- };
- Node node[N];
- int cur;
- int hashTable[H];
- void initHash()
- {
- cur = 0;
- for (int i = 0; i < H; ++i) hashTable[i] = -1;
- }
- unsigned int getHash(int* num)
- {
- unsigned int hash = 0;
- for (int i = 0; i < 6; ++i)
- {
- hash += num[i];
- }
- return hash % H;
- }
- bool cmp(int* num1, int* num2)
- {
- for (int i = 0; i < 6; ++i)
- {
- if (num1[i] != num2[i]) return false;
- }
- return true;
- }
- void insertHash(int* num, unsigned int h)
- {
- for (int i = 0; i < 6; ++i) node[cur].num[i] = num[i];
- node[cur].next = hashTable[h];
- hashTable[h] = cur;
- ++cur;
- }
- bool searchHash(int* num)
- {
- unsigned h = getHash(num);
- int next = hashTable[h];
- while (next != -1)
- {
- if (cmp(num, node[next].num)) return true;
- next = node[next].next;
- }
- insertHash(num, h);
- return false;
- }
- int main()
- {
- int num[2][12];
- int n;
- bool twin = false;
- initHash();
- scanf("%d", &n);
- while (n--)
- {
- for (int i = 0; i < 6; ++i)
- {
- scanf("%d", &num[0][i]);
- num[0][i + 6] = num[0][i];
- }
- if (twin) continue;
- for (int i = 0; i < 6; ++i)
- {
- num[1][i + 6] = num[1][i] = num[0][5 - i];
- }
- for (int i = 0; i < 6; ++i)
- {
- if (searchHash(num[0] + i) || searchHash(num[1] + i))
- {
- twin = true;
- break;
- }
- }
- }
- if (twin) printf("Twin snowflakes found.\n");
- else printf("No two snowflakes are alike.\n");
- return 0;
- }