相同的雪花----Hash和循环左移的实现

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=130

解题思路:对于每种边长的输入,将边长和作为Hash值,使用静态链表next(结构体数组)处理冲突。将所有可能的边长顺序存储在next链表中。当有新元素插入静态链表时采用从头插入的方式插入新的边长序列。

对于一组边长序列,使用循环左移和循环右移的方式求的虽有可能的边长顺序序列:

假如输入的边长序列是1 2 3 4 5 6,设置两个长度是10的序列。其中一个存储1 2 3 4 5 6 1 2 3 4 5,从左到右每六个读取,相当于实现了循环左移;另一个存储6 5 4 3 2 1 6 5 4 3 2,从左到右每六个读取,相当于实现了循环右移。每次生成一个新的序列顺序,将其添加到next静态链表中。

代码如下:

  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.   
  6. const int N = 1200010;  
  7. const int H = 1200007;  
  8.   
  9. struct Node  
  10. {  
  11.     int num[6];  
  12.     int next;  
  13. };  
  14. Node node[N];  
  15. int cur;  
  16. int hashTable[H];  
  17.   
  18. void initHash()  
  19. {  
  20.     cur = 0;  
  21.     for (int i = 0; i < H; ++i) hashTable[i] = -1;  
  22. }  
  23.   
  24. unsigned int getHash(int* num)  
  25. {  
  26.     unsigned int hash = 0;  
  27.     for (int i = 0; i < 6; ++i)  
  28.     {  
  29.         hash += num[i];  
  30.     }  
  31.     return hash % H;  
  32. }  
  33.   
  34. bool cmp(int* num1, int* num2)  
  35. {  
  36.     for (int i = 0; i < 6; ++i)  
  37.     {  
  38.         if (num1[i] != num2[i]) return false;  
  39.     }  
  40.     return true;  
  41. }  
  42.   
  43. void insertHash(int* num, unsigned int h)  
  44. {  
  45.     for (int i = 0; i < 6; ++i) node[cur].num[i] = num[i];  
  46.     node[cur].next = hashTable[h];  
  47.     hashTable[h] = cur;  
  48.     ++cur;  
  49. }  
  50.   
  51. bool searchHash(int* num)  
  52. {  
  53.     unsigned h = getHash(num);  
  54.     int next = hashTable[h];  
  55.     while (next != -1)  
  56.     {  
  57.         if (cmp(num, node[next].num)) return true;  
  58.         next = node[next].next;  
  59.     }  
  60.     insertHash(num, h);  
  61.     return false;  
  62. }  
  63.   
  64. int main()  
  65. {  
  66.     int num[2][12];  
  67.     int n;  
  68.     bool twin = false;  
  69.     initHash();  
  70.     scanf("%d", &n);  
  71.     while (n--)  
  72.     {  
  73.         for (int i = 0; i < 6; ++i)   
  74.         {  
  75.             scanf("%d", &num[0][i]);  
  76.             num[0][i + 6] = num[0][i];  
  77.         }  
  78.         if (twin) continue;  
  79.         for (int i = 0; i < 6; ++i)  
  80.         {  
  81.             num[1][i + 6] = num[1][i] = num[0][5 - i];  
  82.         }  
  83.         for (int i = 0; i < 6; ++i)   
  84.         {  
  85.             if (searchHash(num[0] + i) || searchHash(num[1] + i))  
  86.             {  
  87.                 twin = true;  
  88.                 break;  
  89.             }  
  90.         }  
  91.     }  
  92.     if (twin) printf("Twin snowflakes found.\n");  
  93.     else printf("No two snowflakes are alike.\n");  
  94.     return 0;  
  95. }  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值