数字hash _ 熟练掌握数组当作链表来用的技能

来源:互联网 发布:哪个导航软件最好用 编辑:程序博客网 时间:2024/06/01 09:58

通过这道题要熟练掌握把数组当作链表来用的技能,这和图的邻接表的数组实现及其应用基于同样的原理。


本题题目链接Snowflake Snow Snowflakes

每个雪花都有六个分支,用六个整数代表,这六个整数是从任意一个分支开始,朝顺时针或逆时针方向遍历得到的。输入多个雪花,判断是否有形状一致的雪花存在。

简单的数字哈希,要注意的是每种雪花可以由多种数字组合表示。

比如输入的是1 2 3 4 5 6,

则2 3 4 5 6 1,3 4  5 6 1 2,……,6 5 4 3 2 1,5 4 3 2 1 6等都是相同形状的。

原文是(因此可以在读入一个雪花的时候把这些情况全部放入哈希表中)

但我给改成只插入一次雪花,而非12次。

如果某次插入的时候存在重复的雪花,那么后面的不需要再处理。

#include <iostream>  #include <cstdio>  #include <algorithm>  using namespace std;    const int N = 100001;  const int H = 100001; typedef struct node{int arm[6];int next;          //记录同哈希值的雪花的上一编号 }Node; Node node[N];int counter;           //雪花编号,一直是累加的 int hashtable[H];void initial_hash(){    counter=0;for(int i=0;i<H;i++){hashtable[i]=-1;   //前继无人 }}bool compare(int *arm1,int *arm2){     for (int i = 0; i < 6; ++i)      {          if (arm1[i] != arm2[i])     return false;      }      return true; } unsigned get_hash(int *arm){unsigned int total=0;for(int i=0;i<6;i++){total+=arm[i];}return total % H;}void insert(int *arm,unsigned int h){for(int i=0;i<6;i++){node[counter].arm[i]=arm[i];}node[counter].next=hashtable[h];hashtable[h]=counter++;     //counter是雪花编号,一直是累加的 }bool search(int *arm){int h=get_hash(arm);for(int i=hashtable[h];i!=-1;i=node[i].next){if(compare(node[i].arm,arm))   return true;}    /* 把这句挪到主函数中的循环匹配函数后,只有在匹配失败后才插入;   否则按照原来的写法,需要插入12次同样的雪花     insert(arm,h);     */return false;}int main()  {      int arm[2][11];   //不用12列,只用11列就够了     int n;      bool twin = false;      initial_hash();    scanf("%d", &n);      while (n--)      {          for (int i = 0; i < 6; ++i)           {              scanf("%d", &arm[0][i]);              arm[0][i + 6] = arm[0][i];          }          if (twin) continue;     //已经匹配了之后,就不管后面的输入了         for (int i = 0; i < 6; ++i)          {              arm[1][i + 6] = arm[1][i] = arm[0][5 - i];          }          /*上面两个for循环是为了处理所有的雪花情况——顺时针、逆时针、错位等,共12种情况*/                int i;        for ( i = 0; i < 6; ++i)           {          //每一种情况(雪花的旋转)都要search,每一次search都有不定数量的compare(和同组相同哈希值的雪花进行比较)        //相同的hash值不意味着雪花相等,敌不动我动,只有待插入(比较)的雪花才旋转,已经插入的不动,等待比较             if (search(arm[0] + i) || search(arm[1] + i))              {                  twin = true;                  break;              }          }     if(i==6) {   //没找到才插入一次(最原始的雪花) insert(arm[0],get_hash(arm[0])); }    }         if (twin)     printf("Twin snowflakes found.\n");      else     printf("No two snowflakes are alike.\n");      return 0;  }


转载自点击打开链接,代码有修改(原文是每个雪花12种情况都要插入hash表 ,我是只插一次,原文是对的,我也是对的)

0 0
原创粉丝点击