分析:
对于一个六边形,长度个不一个样,而物体可以旋转,这是一个很头痛的问题,该如何辨别这些相同的六边形,链表?这显然不好,用map行不通,想想看,
比如:1 2 3 4 5 6和1 2 2 3 4 5,他们的和是不同的,所以我们直接就可以否定他们相同,但对于 1 2 3 4 5 6和 1 3 2 4 6 5,他们的和是相同的,但属于不同的
六边形,这些数据有些好辨别,有些不好辨别,我们应该让他们离散化,尽可能的让他们离散,由于sum和可能很大,我们就mod一个数就是让他们离散化,
对于余数相同的,我们就hash吧!。
hash思想:对于很多数据,存在个体差别和个体相同,要查找一个数据,很不容易,我们就先把它们离散化,离散化并不能消除个体相同的,但在很大程度上
降低了查找数据的难度,对于转化后的数据,还是相同,我们就把它放在一起(即放在同一行)。这样我就根据该行,一次找下去,就可以了。说白了,hash思想的
精粹就是:类比思想。一大批数据,我们只要对这些数在一个特定的M(方式),在M的处理下,每个数据有个映射,沿着这条路径,可以彼此建立联系,把原问题转化成
另一个问题,大大降低难度了。
好好体会这种思想!
本题代码如下:
#include<stdio.h>
#include<string.h>
#define H 1000000
#define N 2000000
struct node{
int date[6];
int next;
}Node[N];
int hashtable[N],cnt=0;
int get_hash(int *num)
{
int sum=0;
for(int i=0;i<6;i++)
sum=(sum+num[i])%H;
return sum;
}
bool cmp(int *num1,int *num2){
for(int i=0;i<6;i++){
if(num1[i]!=num2[i])
return false;
}
return true;
}
void insert (int *num,int x){
for(int i=0;i<6;i++){
Node[cnt].date[i]=num[i];
}
Node[cnt].next=hashtable[x];
hashtable[x]=cnt++;
}
bool search(int *num){
int r=get_hash(num);
int m=hashtable[r];
while(m!=-1){
if(cmp(num,Node[m].date)) return true;
m=Node[m].next;
}
insert(num,r);
return false;
}
int main()
{
int num[2][12],t,i,flag=0;
memset(hashtable,-1,sizeof(hashtable));
scanf("%d",&t);
while(t--){
for(i=0;i<6;i++){
scanf("%d",&num[0][i]);
num[0][6+i]=num[0][i]; //构造循环
}
for(i=0;i<6;i++){
num[1][i+6]=num[1][i]=num[0][5-i]; //构造反循环 ,巧妙之处。
}
for(i=0;i<6;i++){
if(search(num[0]+i)||search(num[1]+i))
{
flag=1;
break;
}
}
}
if(flag) printf("Twin snowflakes found.\n");
else printf("No two snowflakes are alike.\n");
return 0;
}