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=100000+5; const int MOD=999991; int Num[MAXN][6]; //data storage struct Node{ int id,next; }Snow[MAXN]; int Scnt,Head[MOD];//list table void Init(){ //initialization memset(Head,-1,sizeof(Head)); Scnt=0; } 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=0;i<6;i++){ //Sequence order bool flag=true; for(int st=i,j=0;j<6;j++,st=(st+1==6?0:st+1)){ if(Num[idx][st]!=Num[idy][j]){ flag=false; } } if(flag){ return true; } } for(int i=0;i<6;i++){ //Reverse order bool flag=true; for(int st=i,j=0;j<6;j++,st=(st-1==(-1)?5:st-1)){ if(Num[idx][st]!=Num[idy][j]){ flag=false; } } if(flag){ return true; } } return false; } bool solve(int id){ int HashNum=0; for(int i=0;i<6;i++){ // make hash HashNum=(HashNum%MOD+(Num[id][i])%MOD)%MOD; } for(int i=Head[HashNum];i!=-1;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=0;i<n;i++){ for(int j=0;j<6;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 0; }