题意:给定n片雪花(0 < n ≤ 100000),每片雪花有六个角(大小不同,数字表示),问你有没有两个或以上片雪花完全相同。
注意事项 1->雪花可以翻转、向左(右)移动,例如
1 2 3 4 5 6 4 3 2 1 6 5 是符合的。2->直接枚举会超时,可以利用哈希表雪花离散化,不必一个一个查之前的雪花。
3->先查找,确定该雪花不存在再把该雪花插入哈希表,有两种方案,第一,把每个雪花转六下,分别在哈希里面找,然后翻转,把每个雪花转六下,分别在哈希里面找,最后在两种状态插入hash表(翻转之前,翻转之后)。
题目连接:http://poj.org/problem?id=3349
//该代码在poj,nyoj ac<pre name="code" class="cpp"><pre name="code" class="cpp">//数组模拟指针,实现hash会比vector快
#include<stdio.h>#include<string.h>#define T 100007int L;int table[T];struct node{int a[10];}nod;struct lis{struct node x;int next;}list[300010];int get_hash(struct node &nod) //利用&时间会快500ms{int i,s;s=0;for(i=0;i<6;i++){s+=nod.a[i];}s%=T;return s;}int find(struct node &nod)
//利用&时间会快500ms
{
int i;
int hash=get_hash(nod);
int next=table[hash];
while(next!=-1)
{
for(i=0;i<6;i++)
{
if(nod.a[i]!=list[next].x.a[i])
break;
}
if(i==6)
return 1;
next=list[next].next;
}
return 0;
}
int main()
{
int i,j,k,n,m,ok,hash,a0,a1,a2;
while(scanf("%d",&n)!=EOF)
{
L=0;
ok=0;
memset(table,-1,sizeof(table));
while(n--)
{
for(j=0;j<6;j++)
scanf("%d",&nod.a[j]);
for(i=0;i<6;i++)
{
if(find(nod)==1)
{
ok=1;
}
k=nod.a[0];
for(j=1;j<6;j++)
{
nod.a[j-1]=nod.a[j];
}
nod.a[5]=k;
}
if(ok)
continue;
if(!ok)
{
hash=get_hash(nod);
list[L].next=table[hash];
list[L].x=nod;
table[hash]=L++; //利用数组模拟指针,实现hash会比vector快
a0=nod.a[0];a1=nod.a[1];a2=nod.a[2];
nod.a[0]=nod.a[5];
nod.a[1]=nod.a[4];
nod.a[2]=nod.a[3];
nod.a[5]=a0;
nod.a[4]=a1;nod.a[3]=a2;
for(i=0;i<6;i++)
{
if(find(nod)==1)
{
ok=1;
}
k=nod.a[0];
for(j=1;j<6;j++)
{
nod.a[j-1]=nod.a[j];
}
nod.a[5]=k;
}
if(!ok)
{
hash=get_hash(nod);
list[L].next=table[hash];
list[L].x=nod;
table[hash]=L++;
}
}
}
if(ok)
{
printf("Twin snowflakes found.\n");
}
else printf("No two snowflakes are alike.\n");
}
}
该代码在nyoj已过,但是poj超时,vector会比上面的慢!!!
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
#define T 100007
struct node
{
int a[10];
}nod;
vector<struct node > vec[T];
int get(int a[])
{
int i,hash,s,ok,j;
hash=0;
for(j=0;j<6;j++)
{
hash+=a[j]*(j+1);
}
hash%=T;
int L=vec[hash].size();
ok=0;
for(i=0;i<L;i++)
{
for(j=0;j<6;j++)
{
if(vec[hash][i].a[j]!=a[j])
{
ok=0;
break;
}
}
if(j==6)
{
ok=1;
break;
}
}
if(ok)
return 1;
else return 0;
}
int main()
{
int a[10];
int ia[10];
int i,j,k,n,m,ok,t,d,hash,d0,d1,d2;
//scanf("%d",&n);
//while(n--)
{
for(i=0;i<T;i++)
vec[i].clear();
ok=0;
scanf("%d",&t);
for(i=0;i<t;i++)
{
for(j=0;j<6;j++){
scanf("%d",&a[j]);
}
if(ok)
continue;
for(d=0;d<6;d++){
k=a[5];
for(j=4;j>=0;j--)
{
a[j+1]=a[j];
}
a[0]=k;
if(get(a))
{
ok=1;
break;
}
}
if(!ok)
{
nod.a[0]=a[0];nod.a[1]=a[1];nod.a[2]=a[2];
nod.a[4]=a[4];nod.a[3]=a[3];nod.a[5]=a[5];
hash=0;
for(j=0;j<6;j++)
{
hash+=a[j]*(j+1);
}
hash%=T;
vec[hash].push_back(nod);
hash=0;
d0=a[0];d1=a[1];d2=a[2];
a[0]=a[5];a[1]=a[4];a[2]=a[3];
a[3]=d2;a[4]=d1;a[5]=d0;
nod.a[0]=a[0];nod.a[1]=a[1];nod.a[2]=a[2];
nod.a[4]=a[4];nod.a[3]=a[3];nod.a[5]=a[5];
for(j=0;j<6;j++)
{
hash+=a[j]*(j+1);
}
hash%=T;
vec[hash].push_back(nod);
}
}
if(ok)
printf("Twin snowflakes found.\n");
else {
printf("No two snowflakes are alike.\n");
}
}
}