这道题我用的是hash。之前用map TLE了。看discuss发现得用hash。事实是hash要比map快很多。
这里的hash用的是最简单的求和再对一个大prime(999331)取余。
另外用到了数组形式的链表。用一个next数组保存下一个同hash的snowflake的位置。
要对同hash的所有snowflake按照链表一一判断是否相同。这里判断就是老老实实地对不同起点进行遍历,每次都顺时针和逆时针各判断一次。
从discuss的反馈来看,似乎只要6个数相同就可以判断相同了,因而有更快更简单的做法,比如排序。但是应该是与题意不符的。
thestoryofsnow | 3349 | Accepted | 6792K | 2188MS | C++ | 2219B |
/*
ID: thestor1
LANG: C++
TASK: poj3349
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>
using namespace std;
const int MAXN = 100000;
const int MOD = 999331;
bool cmp(int snowflake1[], int snowflake2[])
{
int min1 = *min_element(snowflake1, snowflake1 + 6);
int max1 = *max_element(snowflake1, snowflake1 + 6);
int min2 = *min_element(snowflake2, snowflake2 + 6);
int max2 = *max_element(snowflake2, snowflake2 + 6);
if (min1 != min2 || max1 != max2)
{
return false;
}
bool same = false;
for (int i = 0; i < 6; ++i)
{
// clockwise
int j = 0;
for (j = 0; j < 6; ++j)
{
if (snowflake1[(i + j) % 6] != snowflake2[j])
{
break;
}
}
if (j == 6)
{
same = true;
break;
}
// counterclockwise
j = 0;
for (j = 0; j < 6; ++j)
{
if (snowflake1[(i - j + 6) % 6] != snowflake2[j])
{
break;
}
}
if (j == 6)
{
same = true;
break;
}
}
return same;
}
int main()
{
int snowflakes[MAXN][6];
int next[MAXN];
int starters[MAXN * 10];
memset(starters, -1, MAXN * 10 * sizeof(int));
int n;
scanf("%d", &n);
bool duplicate = false;
for (int i = 0; i < n; ++i)
{
next[i] = -1;
for (int j = 0; j < 6; ++j)
{
scanf("%d", &snowflakes[i][j]);
}
if (duplicate)
{
continue;
}
int hashval = 0;
for (int j = 0; j < 6; ++j)
{
hashval += snowflakes[i][j];
}
hashval %= MOD;
if (starters[hashval] == -1)
{
starters[hashval] = i;
}
else
{
int starter = starters[hashval];
while (starter != -1)
{
if (cmp(snowflakes[i], snowflakes[starter]))
{
duplicate = true;
break;
}
starter = next[starter];
}
next[i] = starters[hashval];
starters[hashval] = i;
}
}
if (!duplicate)
{
printf("No two snowflakes are alike.\n");
}
else
{
printf("Twin snowflakes found.\n");
}
return 0;
}