http://poj.org/problem?id=3349
题意,给出6个数表示 一种六边形
a1 a2 a3 a4 a5 a6
如果存在另一组 6个数 为 a数组平移得到,或者 翻转得到,那么 它代表的六边形与 a数组代表六边形是同一个
给出n组 这样的6元素数组,求其中是否有 2个 代表同一个六边形
对每给出的一组数据,可以对其6个数 用拉链法得到 一共 12个hash值,显然我们不可能把全部hash值都拿去判断。。必然TLE到死。。。
我们可以再哈希出一个 值, 这里窝直接 采用 12个中最小的 一个 作为 这个六边形的 最终hash值
然后求出所有的hash值比较有没相同的即可
判断是否出现过 用到开放定址法的二次探测。。。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
typedef unsigned long long ull;
const ull mod= 149997 ;
const ull p=239;
ull min(ull a,ull b){return a<b?a:b;}
ull max(ull a,ull b){return a>b?a:b;}
ull pp[10];
ull val[14];
int tm[100000+5][10];
ull has[150000+5];
void pre(int x)
{
int i,j;
ull tmp=0;
for (i=0;i<=5;i++)
{
int times=6;
tmp=0;
for (j=i;times--;j=(j+1)%6)
{
tmp=(tmp+tm[x][j]*pp[times]);
}
val[i]=tmp;
}
for (i=0;i<=5;i++)
{
int times=6;
tmp=0;
for (j=i;times--; )
{
tmp=(tmp+tm[x][j]*pp[times]);
j--;
if (j<0) j=5;
}
val[6+i]=tmp;
}
}
int main()
{
int n,i,j;
pp[0]=p;
for (i=1;i<=5;i++)
pp[i]=pp[i-1]*p;
cin>>n;
for (i=1;i<=n;i++)
{
for (j=0;j<=5;j++)
{
scanf("%d",&tm[i][j]);
}
}
int flag=0;
for (i=1;i<=n;i++)
{
pre(i);
ull ret=val[0];
for (j=0;j<12;j++)
ret=min(ret,val[j]);
int dd=ret%mod;
int tmp=dd,t=1;
while(has[tmp]!=0)
{
if (has[tmp]==ret)
{flag=1;break;}
tmp=(dd+t*t)%mod;
t++;
}
if (flag) break;
else
has[tmp]=ret;
}
if (flag)
printf("Twin snowflakes found.\n");
else
printf("No two snowflakes are alike.\n");
return 0;
}