POJ 3349 HASH

时间:2023-03-08 22:56:47
POJ 3349 HASH

题目链接:http://poj.org/problem?id=3349

题意:你可能听说话世界上没有两片相同的雪花,我们定义一个雪花有6个瓣,如果存在有2个雪花相同[雪花是环形的,所以相同可以是旋转过后相同]则输出“Twin snowflakes found.”,否则输出“No two snowflakes are alike.”。

思路:最简单的就是两两判断,但是这样的复杂度为O(n^2),TLE。所以我们要尽量减少判断次数,我们用把拥有6个瓣的雪花HASH成一个数字,只有两个雪花用有相同HASH值时才有"可能"相同,然后HASH难免会有冲突,所以用拉链法解决冲突。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<time.h>
#include<set>
using namespace std;
typedef long long int LL;
const int MAXN=+;
const int MOD=;
int Num[MAXN][]; //data storage
struct Node{
int id,next;
}Snow[MAXN];
int Scnt,Head[MOD];//list table
void Init(){ //initialization
memset(Head,-,sizeof(Head));
Scnt=;
}
void AddNode(int HashN,int idx){
Snow[Scnt].id=idx;
Snow[Scnt].next=Head[HashN];
Head[HashN]=Scnt++;
}
bool cmp(int idx,int idy){ //compare two Snowflake
for(int i=;i<;i++){ //Sequence order
bool flag=true;
for(int st=i,j=;j<;j++,st=(st+==?:st+)){
if(Num[idx][st]!=Num[idy][j]){
flag=false;
}
}
if(flag){
return true;
}
}
for(int i=;i<;i++){ //Reverse order
bool flag=true;
for(int st=i,j=;j<;j++,st=(st-==(-)?:st-)){
if(Num[idx][st]!=Num[idy][j]){
flag=false;
}
}
if(flag){
return true;
}
}
return false;
}
bool solve(int id){
int HashNum=;
for(int i=;i<;i++){ // make hash
HashNum=(HashNum%MOD+(Num[id][i])%MOD)%MOD;
}
for(int i=Head[HashNum];i!=-;i=Snow[i].next){//get the same hash value
if(cmp(id,i)){//compare
return true;
}
}
AddNode(HashNum,id); //insert into hash table
return false;
}
int main(){
#ifdef kirito
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int start=clock();
int n,val;
while(~scanf("%d",&n)){
bool flag=false; Init();
for(int i=;i<n;i++){
for(int j=;j<;j++){
scanf("%d",&Num[i][j]);
}
if(flag){continue;}
if(solve(i)){
flag=true;
}
}
if(!flag){
printf("No two snowflakes are alike.\n");
}
else{
printf("Twin snowflakes found.\n");
}
}
#ifdef LOCAL_TIME
cout << "[Finished in " << clock() - start << " ms]" << endl;
#endif
return ;
}