自己写的第一个hash。思路比较复杂:
以六个数的平方和作为key。hash function为index=key mod 99991(99991为不大于100 000的最大质数)。将这个key保存到f[index]中。如果碰到有相同key值的数(相同key但不一定完全相同雪花),对这两片雪花进行仔细的比较,如果相同则返回;如果不同将此key保存到f[index2]。hash function为index2=((key mod 99990)+1+index)mod 99991。
复杂的思路造就复杂的算法,以下是TLE版本:
![]()
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAXSIZE 100000
double f[MAXSIZE];
double m[MAXSIZE][6];//储存读入的数据
int judge(double key, double *num)
{
int index, i, flag=0, j, count;
index=(int)fmod(key, 99991);//hash function 1
while (f[index]!=-1.0){
if (f[index]==key){
//////////////////////////////////////////////////////////////////////////
for (i=0;i<6;i++){
//对照两片雪花是否相同
if (flag==0 && num[i]==m[index][0]){
count=1;
//顺时针查找
for (j=1;j<6;j++){
if (m[index][j]!=num[(i+j)%6]){
break;
}
count++;
}
if (count==6){
return 1;
}
//逆时针查找
if (flag==0){//如果顺时针没有查到
count=1;
for (j=1;j<6;j++){
if (m[index][j]!=num[(i-j+6)%6]){
break;
}
count++;
}
if (count==6){
return 1;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
}
index=(int)fmod((fmod(key, 99990)+1+index), 99991);//hash function 2
}
f[index]=key;
for (i=0;i<6;i++){
m[index][i]=num[i];
}
return 0;
}
int main()
{
int n, i, j, flag;
double num[6], key;
//memset(f, -1, MAXSIZE);
for (i=0;i<MAXSIZE;i++){
f[i]=-1.0;
}
//freopen("input.txt", "r", stdin);
while (scanf("%d", &n)!=EOF){
for (j=0;j<n;j++){
key=0;
for (i=0;i<6;i++){
scanf("%lf", &num[i]);
key+=num[i]*num[i];
}
flag=judge(key, num);
if (flag==1){
printf("Twin snowflakes found.\n");
return 1;
}
}
}
printf("No two snowflakes are alike.\n");
return 1;
}
对以上的TLE版本进行一点小修改:第一,以六个数之和mod 99991作为key,这样就可以用int代替了double;第二,用拉链法代替开地址法,提高效率;第三,读数字用getchar()代替scanf(),同样提高了效率。最后3922ms惊现AC。。。
| Run ID |
User |
Problem |
Result |
Memory |
Time |
Language |
Code Length |
Submit Time |
| 5123591 |
zen_chou |
3349 |
Accepted |
6472K |
3922MS |
C |
1464B |
2009-05-09 17:25:29 |
![]()
Code
1 #include <stdio.h>
2 #include <memory.h>
3 #define PRIME 99991
4 #define MAX 100000
5 int num[MAX][6];//存放读入的数据
6 int hash[MAX][10];
7 int same(int key, int pos, int index)
8 {
9 int i, j, flag=0, count, orgidx;
10 orgidx=hash[key][pos];
11 for (i=0;i<6;i++){
12 //对照两片雪花是否相同
13 if (flag==0 && num[orgidx][i]==num[index][0]){
14 count=1;
15 //顺时针查找
16 for (j=1;j<6;j++){
17 if (num[index][j]!=num[orgidx][(i+j)%6]){
18 break;
19 }
20 count++;
21 }
22 if (count==6){
23 return 1;
24 }
25 //如果顺时针没有查到,逆时针查找
26 if (flag==0){
27 count=1;
28 for (j=1;j<6;j++){
29 if (num[index][j]!=num[orgidx][(i-j+6)%6]){
30 break;
31 }
32 count++;
33 }
34 if (count==6){
35 return 1;
36 }
37 }
38 }
39 }
40 return 0;
41 }
42 int judge(int key, int index)
43 {
44 int pos=0;
45 while (hash[key][pos]!=-1){
46 if (same(key, pos, index)){
47 return 1;
48 }
49 else{
50 pos++;
51 }
52 }
53 hash[key][pos]=index;
54 return 0;
55 }
56 int main()
57 {
58 int n, j, i, c, k, key, flag;
59 //freopen("input.txt", "r", stdin);
60 memset(hash, -1, sizeof(hash));
61 scanf("%d", &n);
62 getchar();
63 for (j=0;j<n;j++){
64 key=0;
65 for (i=0;i<6;i++){
66 c=getchar();
67 k=0;
68 while (c!='\n' && c!=' '){
69 k=k*10+c-'0';
70 c=getchar();
71 }
72 key+=k;
73 num[j][i]=k;
74 }
75 key%=PRIME;
76 flag=judge(key, j);
77 if (flag==1){
78 printf("Twin snowflakes found.\n");
79 return 1;
80 }
81 }
82 printf("No two snowflakes are alike.\n");
83 return 1;
84 }
85
参考:http://www.cppblog.com/RyanWang/archive/2008/11/19/67271.html, http://blog.csdn.net/suikay/archive/2009/03/29/4033415.aspx