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; }