题目大意:意思还是很好理解的,雪花有六个臂,给出每个臂长,从而寻找n组雪花里是否有相同的两片,不过比较疑惑的是相同的雪花应该是所有臂的长度一一对应,可是如果不比较顺序,之比较两组的六臂是否为同一集合仍可以AC,这测试数据还是有点问题的,所以,忽视吧。。
题目链接:http://poj.org/problem?id=3349
方法:hash
思路:如果不比较顺序就蛮好做了(比较顺序会麻烦一些),就是用hash做,可能有些同学不太懂hash,以我理解,hash就是通过对某些量进行hash数组的下标表示,散列存储,这样后面比较会很快捷,不过往往是会使用到大数组,不过用内存换速度还是值得的。。当然也可以对一个大素数取模,这样数组可以开小很多,而且往往避免了一些冲突,那么在此题中,我们可以记录六臂的长度和,然后对大素数取模(这个素数可以适当开大点,这样比较的次数会减少),通过检测这个下标对应的数组是否有过记录,若有,则比较,如无,则记录,并且记录六臂,所以这里用了三个数组,一个原始存储数据,一个记录该下标点是否有数据,一个记录该下标点的六臂长,这里用hash的目的就是减少比较次数,如果一个一个比较,必然超时,若果有什么而不懂,可以留言,同时希望大神指教。。
算法实现:
#include<stdio.h>
#include<memory.h>
const int M=50021;//定义一个大素数,从而通过取模减小内存。
int hash[50022][7],sel[50022],a[100001][7];
int main()
{
int n,i,j,sum,k,ok1,ok2,ok3;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<6;j++)
scanf("%d",&a[i][j]);
memset(sel,0,sizeof(sel));
memset(hash,0,sizeof(hash));
ok3=0;
for(i=0;i<n;i++)
{
sum=0;
for(j=0;j<6;j++)
sum+=a[i][j];
sum=sum%M;//因为sum可能很大,所以对一个大素数取模,这样减小hash数列的范围。
if(sel[sum]==0)//sel数组用来判断此时hash数组上对应的是否已存在,不存在则记录1,且将此部分赋给hash数组。
{
sel[sum]=1;
for(k=0;k<6;k++)
hash[sum][k]=a[i][k];
}
else//如该位置上已存在,则比较是否相同。
{
for(k=0;k<6;k++)//比较两集合是否互为子集。
{
ok1=0;
for(j=0;j<6;j++)
if(hash[sum][k]==a[i][j])
{
ok1=1;
break;
}
if(ok1==0)
{
break;
}
}
for(k=0;k<6;k++)
{
ok2=0;
for(j=0;j<6;j++)
if(hash[sum][j]==a[i][k])
{
ok2=1;
break;
}
if(ok2==0)
break;
}
if(ok1==1&&ok2==1)//互为子集则有相同的,输出并退出,不用再循环。
{
printf("Twin snowflakes found.\n");
ok3=1;
break;
}
}
}
if(ok3==0)
printf("No two snowflakes are alike.\n");
return 0;
}