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

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


本题题目链接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表 ,我是只插一次,原文是对的,我也是对的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值