POJ 3349 Snowflake Snow Snowflakes(数字哈希)

Description

You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Your program will read information about a collection of snowflakes, and search for a pair that may be identical. Each snowflake has six arms. For each snowflake, your program will be provided with a measurement of the length of each of the six arms. Any pair of snowflakes which have the same lengths of corresponding arms should be flagged by your program as possibly identical.

Input

The first line of input will contain a single integer n, 0 < n ≤ 100000, the number of snowflakes to follow. This will be followed by n lines, each describing a snowflake. Each snowflake will be described by a line containing six integers (each integer is at least 0 and less than 10000000), the lengths of the arms of the snow ake. The lengths of the arms will be given in order around the snowflake (either clockwise or counterclockwise), but they may begin with any of the six arms. For example, the same snowflake could be described as 1 2 3 4 5 6 or 4 3 2 1 6 5.

Output

If all of the snowflakes are distinct, your program should print the message:
No two snowflakes are alike.
If there is a pair of possibly identical snow akes, your program should print the message:
Twin snowflakes found.

Sample Input

2
1 2 3 4 5 6
4 3 2 1 6 5

Sample Output

Twin snowflakes found.



#include <iostream>
#include <stdio.h>
using namespace std;


const int N = 1200010;  
const int H = 1200007;
struct Node{
	int num[6];
	int next;//the next saves its hash
}node[N];

int hashTable[H];

int cur;//记录当前雪花的位置
void initHash(){
	cur=0;
	for(int i=0;i<H;i++) hashTable[i]=-1;
}

int getHash(int num[]){
	int h=0;//非输入变量一定要初始化
	for(int i=0;i<6;i++) h+=num[i];
	return h%H;
}

bool cmp(int num1[],int num2[]){
	for(int i=0;i<6;i++)
		if(num1[i]!=num2[i])
			return false;
	return true;		
}

void insertHash(int num[],int h){
	for(int i=0;i<6;i++) node[cur].num[i]=num[i];
	node[cur].next=hashTable[h];
	hashTable[h]=cur;
	cur++;
}

bool searchHash(int num[]){
	int h=getHash(num);
	int next=hashTable[h];
	while(next!=-1){
		if(cmp(num,node[next].num)) return true; //judge if the equal hash is similar 
		next=node[next].next;
	}
	insertHash(num,h);
	return false;
}
int main(){
	
	int n;
	int num[2][12];
	bool twin=false;
	initHash();
	
	scanf("%d",&n);
	while(n--){

		for(int i=0;i<6;i++){
			scanf("%d",&num[0][i]);
			num[0][i+6]=num[0][i];
		}
		
		if(twin) continue;//if twin we can still cin but needn't to judge
		
		for(int i=0;i<6;i++){ //two different diretions to make up a ring 
			num[1][i]=num[0][5-i];
			num[1][i+6]=num[1][i];
		}
		
		for(int i=0;i<6;i++){//regard each length as start to traversal 
			if(searchHash(num[0]+i)||searchHash(num[1]+i)){
				twin=true;
				break;
			}
			
		}
		
		
	}
	
	
	if(twin) printf("Twin snowflakes found.\n");
	else printf("No two snowflakes are alike.\n");
	
	
}

因为要输入很多片雪花,直接比较肯定会T,所以我们先将每片雪花的长度取模作为它的哈希值,再将哈希值相等的雪花逆时针顺时针比较是否相同;

新建node数组存放雪花,num数组代表当前雪花六边的长度,next存放和当前雪花哈希值相等的下一个雪花的位置;

新建hashTable数组,数组下标表示哈希值,数组每一项的值代表当前为这个哈希值的雪花的位置;

对于searchHash函数,用next表示下一个有该哈希值雪花的位置,如果这两个cmp为真则相等,为假则把hashTable当前哈希值的位置指向下一个雪花,下个雪花的next指向前一个哈希值相等的雪花的位置(通过insert函数来实现);

在main函数中输入雪花时会新建一个二维数组,第一行第二行表示雪花长度的顺序(顺时针,逆时针),12列是为了复制一遍成环,比较相等时从每个位置开始走6次,就是雪花的一个方向;

main函数中输入的雪花在searchHash操作中会保存到node数组中,方便输入下一个时可以和前面的比较;

对于node数组的大小,雪花的范围是1~1e6,但是雪花每遍历一个起点都需要储存到数组一次,所以N至少为1e6*12=1.2e7;

hashTable数组的大小也需要比这个值大,并且取模时我们要用到这个大小,所以最好为素数,因此取了1200007;

该题需要严格控制输入输出的时间,要用scanf和printf,记得加上<cstdio>或者<stdio.h>库;

值得思考的一题,同学还提供了vector的实现方法:http://blog.csdn.net/kyoma/article/details/52072718 



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值