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.
");
        }
        else{
            printf("Twin snowflakes found.
");
        }
    }
#ifdef LOCAL_TIME
    cout << "[Finished in " << clock() - start << " ms]" << endl;
#endif
    return 0;
}
原文地址:https://www.cnblogs.com/kirito520/p/5662657.html