【POJ3349】snowflakes

这是一道可以练习哈希表的模板题。关于哈希表的操作均有涉及。

哈希函数的选取是这道题的关键。这道题的关键字是一个长度为6的序列,并且序列与开始顺序、时钟顺序均无关。
因此,采用哈希函数\(H[x]=\Sigma_{i=0}^5a[i]+\prod_{i=0}^5a[i]\),即:用加和乘的相加来进一步保证散列性。
另外,不能采用带“权值“的哈希函数,因为无序性。
另一个小知识点是顺时针和逆时针的操作,顺时针加 k 取模即可,逆时针正常来说减 k 取模即可,不过可能出现负数,因此再加上6。

代码如下

#include <cstdio>
using namespace std;
const int maxn=1e5+10;
const int mod=1e6+3;

int n,d[6];
struct node{
	int nxt,snow[6];
}t[maxn];
int tot=1,head[mod];

int calc(int p[6]){
	int add=0,mul=1;
	for(int i=0;i<6;i++){
		add=(add+p[i])%mod;
		mul=(long long)mul*p[i]%mod;
	}
	return (add+mul)%mod;
}

bool equal(int a[6],int b[6]){
	for(int i=0;i<6;i++)
		for(int j=0;j<6;j++){
			bool f1=1,f2=1;
			for(int k=0;k<6;k++){
				if(a[(i+k)%6]^b[(j+k)%6])f1=0;
				if(a[(i+k)%6]^b[(j-k+6)%6])f2=0;
			}
			if(f1||f2)return 1;
		}
	return 0;
}

bool insert(int a[6]){
	int u=calc(a);
	for(int i=head[u];i;i=t[i].nxt)
		if(equal(t[i].snow,a))
			return 1;
	++tot,t[tot].nxt=head[u],head[u]=tot;
	for(int i=0;i<6;i++)t[tot].snow[i]=a[i];
	return 0;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=0;j<6;j++)scanf("%d",&d[j]);
		if(insert(d))return puts("Twin snowflakes found."),0;
	}
	return puts("No two snowflakes are alike."),0;
}
posted @ 2018-10-23 19:08  shellpicker  阅读(121)  评论(0编辑  收藏  举报