题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=130
题目分析:
很明显这道题的数据量很大,所以不可能进行两两的判断,所以需要将可能相同的数据映射到一个集合中,然后在可能相同的数据集合中进行两两比较。如果两组数据六个数的和相同,那么就有可能是相同的雪花。但是六个数的和可能比较大,怎么把它们分开呢,那只能建立一个hash表,然后通过mod一个比较大的素数来分到相应的集合里面。
关于这个比较大的素数怎么取呢?
六个数的和最大是6*10^7,如果我们允许每个集合最多有100个数据(如果太多的话,比较的时间就会比较长)。那么最大的和为6*10^5。但是不可能按照最大和来取这个素数。大概小十倍左右。具体取法可能需要试一下。
#include<stdio.h>
#include<string.h>
const int N = 19373;
int Hash[N][100][6];
int nLen[N];
bool Judge(int *a, int *b)
{
int i,j,k;
for(i = 0; i < 6; ++i)
{
//顺时针
for(k = 0; k < 6; ++k)
{
if(b[k] != a[(i + k)%6])
break;
}
if(k >= 6)
return true;
//逆时针
for(k = 0; k < 6; ++k)
{
if(b[k] != a[(i +6 - k)%6])
break;
}
if(k >= 6)
return true;
}
return false;
}
int main()
{
int t,n,sum;
int i,j,k;
int a[6];
bool flag;
scanf("%d", &t);
while(t--)
{
flag = false;
memset(nLen, 0, sizeof(nLen));
scanf("%d", &n);
while(n--)
{
sum = 0;
for(i = 0; i < 6; ++i)
{
scanf("%d", &a[i]);
sum += a[i];
}
sum %= N;
for(i = 0; i < 6; ++i)
Hash[sum][nLen[sum]][i] = a[i];
++nLen[sum];
}
for(k = 0; k < N; ++k)
{
for(i = 0; i < nLen[k] - 1; ++i)
{
for(j = i + 1; j < nLen[k]; ++j)
{
if(Judge(Hash[k][i], Hash[k][j]))
{
flag = true;
break;
}
}
if(flag)//找到一个就可以跳出循环了
break;
}
if(flag)
break;
}
if(flag)
printf("Twin snowflakes found.\n");
else
printf("No two snowflakes are alike.\n");
}
}