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 }

 

转载于:https://www.cnblogs.com/gj-Acit/archive/2013/04/16/3025144.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值