POJ3349 Snowflake Snow Snowflakes(哈希表)
题目链接http://poj.org/problem?id=3349
题意是说,有n片雪花,每片雪花都是有6个角,给出每片雪花每个角的长度,问里面有没有一样的雪花(给出数据的顺序是没有确定的)。
虽然使用了哈希查找表,却还是用了2400多Ms,但还是过了。
这里采用hash数组作为表头,他的下标作为哈希值用于快速定位,next存放的是当hash下标相同时的另一个下标,把他们连接起来,可用于解决矛盾。
如10个数a[]=(下标从1开始,之后会知道为什么)
123456789 ,321654853 ,136977123 ,111234682 ,123458536
222222222 ,454646546 ,787878789 ,919191911, 121321231
哈希函数是
x=a%100;
那么他们哈希值依次是
89 53 23 82 36
22 46 89 11 31
所以除了第7(下标)个外,其他的hash[哈希值]=对应的原数组的下标,如:
hash[89]=1,hash[11]=9,hash[31]=10;
next[0]=1,next[9]=0,next[10]=0
当 插入787878789时,
u=hash[89]=1;(这里就可以看出上面说的为什么下标从1开始,如果下标从0开始的话,u=0,会被误认为没有冲突)
那么next[8]=hash[89]=1;(放的都是下标),hash[89]=8; 这样就能从下表为8找到下标为1的值具体语句是:
while(u){
if(下标为u的已经存在)return flase;
u=next[u];
}
本体代码如下:另外判重的方法在大妈中给出,读者可以好好体会一下(也就是一个小技巧)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<queue> 5 #include<string> 6 #include<stack> 7 #include<cmath> 8 #include<cctype> 9 #include<iostream> 10 #include<set> 11 #include<algorithm> 12 #include<ctime> 13 #include<vector> 14 using namespace std; 15 #define mem(a) memset(a,0,sizeof(a)) 16 #define MAXN 1000007 17 int hash[MAXN],next[MAXN]; 18 int snow[100007][6]; 19 bool isfind; 20 bool judge(int a,int b)//比较下标为a,b的两片雪花是否相同 21 { 22 int i,j,k; 23 for(i=0;i<6;i++) 24 { 25 for(j=i,k=0;k<6;k++,j=(j+1)%6)//顺时针,有一点点小技巧 26 if(snow[a][k]!=snow[b][j])break; 27 if(k==6)return true; 28 for(j=i,k=0;k<6;k++,j=(j+5)%6)//逆时针 29 if(snow[a][k]!=snow[b][j])break; 30 if(k==6)return true; 31 } 32 return false; 33 } 34 35 bool try_to_insert(int a[],int index) 36 { 37 int i,u; 38 int x=0; 39 for(i=0;i<6;i++)//哈希 采用平方取模的方法 40 x=(int)((((long long)a[i]*(long long)a[i])+x)%MAXN); 41 u=hash[x];//hash里面放的是index,即数组的下标,x作为下标,可用于快速查找 42 while(u) 43 { 44 if(judge(index,u))return false; 45 u=next[u]; 46 } 47 next[index]=hash[x];//把下标用next链接起来 48 hash[x]=index;//新的下标作为表头 49 return true; 50 } 51 int main() 52 { 53 int n,j,i; 54 while(~scanf("%d",&n)) 55 { 56 for(i=1;i<=n;i++) 57 for(j=0;j<6;j++) 58 scanf("%d",&snow[i][j]); 59 isfind=false; 60 mem(next);mem(hash);i=1; 61 while(try_to_insert(snow[i],i)&&i<=n) 62 { 63 i++; 64 } 65 if(i==n+1)printf("No two snowflakes are alike.\n"); 66 else printf("Twin snowflakes found.\n"); 67 } 68 return 0; 69 }