这道题目题意很好理解就是在n个元素(每个元素有6个整数组成)中找是否有两个元素相同,这里的相同是指:顺时针或逆时针相同。具体看题目。那么常规的思想就是暴力了,将每个元素与其余n-1个元素比较判断。在这里每两个元素判断相等比较次数为72次,这样的话总共就要比较72×(n*n)次了,而n最大为100000,所以铁定会超时的,就用hash表查找吧!我们在10m(m=100000)范围内找一个最大的素数,做为哈希表的长度prime(注意prime的长度应该要比m大),哈希方程为key=(record)%prime+1;
其中record为每个元素6个整数的和,这样key的范围就是1到prime了,为了避免数据超出范围(这里所有数据都用__int64类型保存),有同余模定理:record[i[%prime,其中i从0到5,相加,然后对结果取一次模。用链地址法解决冲突。算法思想是:每接受一个元素的输入,就对其进行插入并判断,如果不存在该key值,则插入,继续接受输入。若存在,则进一步判断,在该key值位置的链表中是否存在某个元素与当前带插入的元素相同,若存在,则已经找到答案,接下来就只是接受完输入的问题了, 若不存在,则尾插法插入该元素。继续接受输入并判断。不断循环,直到所有的输入都已经输入完毕。然后输出相应的结果。下面简单说明一下怎么判断两个元素相等。当两个元素的key值相等时,只是说明两个元素的6个数字相加和相等,并不能说明元素相等。对!所以,我们在key值相等的情况下,还要进行相应的判断。但是反过来我们可以判定key值不相等的元素绝对不可能相等。这就是hash表的优势,将许多没有必要的比较略去了。同时,也要处理好冲突的问题。应该尽量将冲突降低。达到离散化较好的程度。最理想的情况就是:当我们比较两个元素时,他们是相等的。或者更准确的说是:他们的6个元素的和是相等的。所以这里取的prime为10m以内最大的素数。测试表明这样的离散程度最好。在来说明一下如何判读两个元素相等。由于每个元素可以是逆时针,也可以是顺时针。所以,我们可以分为对应的两种情况讨论。第一种是顺时针,另一种是逆时针,那么具体的内容看代码就很清晰了。下面是代码;
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#define prime 999983
__int64 record[6];
bool exist[prime+1];
struct Hash{
__int64 str[6];
struct Hash *next;
}hash[prime+1];
int n;
__int64 Get_key(){
__int64 t=0;
for(int i=0;i<6;i++)
t+=record[i]%prime;
t%=prime;
return t+1;
}
bool Is_clockwise(const __int64 *p,const __int64 *q){
int i,j,k,t;
bool trag;
for(i=0;i<6;i++){
t=1,j=i,k=0,trag=1;
while(t<=6){
if(p[j]!=q[k]){
trag=0;
break;
}
j=(j+1)%6;
k++;
t++;
}
if(trag)
return 1;
}
return 0;
}
bool Is_countclockwise(const __int64 *p,const __int64 *q){
int i,j,k,t;
bool trag;
for(i=0;i<6;i++){
t=1,j=i,k=0,trag=1;
while(t<=6){
if(j<0)
j=5;
if(p[j]!=q[k]){
trag=0;
break;
}
j--;
k++;
t++;
}
if(trag)
return 1;
}
return 0;
}
bool Insert(){
__int64 key=Get_key();
if(!exist[key]){
for(int i=0;i<6;i++)
hash[key].str[i]=record[i];
hash[key].next=NULL;
exist[key]=1;
return 0;
}
else{
struct Hash *temp=&hash[key];
while(temp->next!=NULL){
if(Is_clockwise(temp->str,record))
return 1;
if(Is_countclockwise(temp->str,record))
return 1;
temp=temp->next;
}
if(Is_clockwise(temp->str,record))
return 1;
if(Is_countclockwise(temp->str,record))
return 1;
struct Hash *te=(struct Hash*)malloc(sizeof(struct Hash));
for(int i=0;i<6;i++)
te->str[i]=record[i];
te->next=NULL;
temp->next=te;
return 0;
}
}
int main(){
scanf("%d",&n);
bool trag=0;
memset(exist,0,sizeof(exist));
while(n--){
for(int i=0;i<6;i++)
scanf("%lld",&record[i]);
if(!trag)
trag=Insert();
}
if(trag)
printf("Twin snowflakes found.\n");
else
printf("No two snowflakes are alike.\n");
return 0;
}