poj.3349

         这道题目的意思很简单就是判断所有的雪花中是否有相似的。相似的判断依据就是其中某一雪花从任意一位置顺时针或逆时针按顺序组成6位数中的所有可能是否有与另一个雪花完全相同的,若有,则说明这两个雪花相似,否则不相似。而题目就是要据此条件判断所有的雪花中是否存在相似的雪花,朴素的算法就是枚举,对任意两个雪花都进行这样的判断。这样的时间复杂度接近为O(n^2),而题目中n的最大值为100000,显然会超时,这里采用哈希查找的办法解决。我们将每个雪花6个数字的长度和作为key进行哈希存放。首先判断雪花的key是否相等,若相等则依据上述条件继续判断是否相似。否则直接就不相似了,因为这是两雪花相似的前提。那么具体的算法流程是:首先在10×n的范围内取最大的素数,作为哈希表的长度。然后以每雪花6个长度的和作为key,建立哈希表。同时建立一个结构体,用来存放雪花的6个长度,以及一个指向同一哈希位置雪花的next指针。并创建一个标记哈希表相应位置是否存在的bool数组,这样,主函数的流程就是,每输入一个雪花的6个长度,首先求其对应的哈希表中的位置,然后判断该位置是否存在雪花,若不存在,则说明已有的雪花中一定没有和该雪花相似的,否则,说明该位置存在雪花,那么同一哈希位置下的雪花可能key值相等,也可能不想等,所以我们在创建哈希表,选择哈希表长度要谨慎。已不能选的太大,防止超内存,也不能选的太小,否则冲突会很多,这样哈希表的优势就体现不了了,这里取10×n内最大的素数为哈希表的长度,这样的取法是比较适中的,冲突会比较少,并采用链地址法解决冲突。当然这里是补充说明上面的哈希表长度为什么取值为10×n以内的数字。接着上面的:若判断在该哈希位置已经存在雪花,那么不管是冲突的,还是本身key值相等的,统一用上面的方法对该哈希位置上的每一个雪花进行相似比较。若存在与其相似的雪花,则直接返回,主函数就不需要在对后续输入的雪花进行相似判断了,否则就将该雪花利用头插法(或尾插法)插入到该哈希位置的链表中。这样一直循环判断。下面是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 999983
struct Node{
	int record[10];
	struct Node *next;
}node[Max];
bool flag[Max];
int Input[10];
int n;
int Get_key(){
	int sum=0;
	for(int i=0;i<6;i++)
		sum+=Input[i];
	return sum%Max;
}
bool Is_clockwise_same(int *p,int *q){
    int *pivot,*move,*index;
	for(pivot=p;pivot-p<6;pivot++){
		if(*pivot==*q){
			int time=0;
		    for(move=pivot,index=q;;){
				if(*move!=*index)
					break;
				else{
					time++;
					if(time==6)
						return 1;
					index++;
					if(move-p==5)
						move=p;
					else
						move++;
				}
			}
		}
	}
	return 0;
}
bool Is_counterclockwise_same(int *p,int *q){
	int *pivot,*move,*index;
	for(pivot=p+5;pivot>=p;pivot--){
		if(*pivot==*q){
			int time=0;
			for(move=pivot,index=q;;){
				if(*move!=*index)
					break;
				else{
					time++;
					if(time==6)
						return 1;
					index++;
					if(move==p)
						move=p+5;
					else
						move--;
				}
			}
		}
	}
	return 0;
}
bool Is_same(int key){
	if(!flag[key]){
		flag[key]=1;
		node[key].next=NULL;
		for(int i=0;i<6;i++)
			node[key].record[i]=Input[i];
		return 0;
	}
	else{
		struct Node *pivot=&node[key];
		while(pivot!=NULL){
			if(Is_clockwise_same(pivot->record,Input)
			|| Is_counterclockwise_same(pivot->record,Input))
			return 1;
			pivot=pivot->next;
		}
		struct Node *temp=(struct Node*)malloc(sizeof(struct Node));
		for(int i=0;i<6;i++)
			temp->record[i]=Input[i];
		temp->next=node[key].next;
		node[key].next=temp;
		return 0;
	}
}
int main(){
	scanf("%d",&n);
	memset(flag,0,sizeof(flag));
	bool trag=0;
	while(n--){
		for(int i=0;i<6;i++)
			scanf("%d",&Input[i]);
		if(trag)
			continue;
		int key=Get_key();
		if(Is_same(key))
			trag=1;
	}
	if(trag)
		printf("Twin snowflakes found.\n");
	else
		printf("No two snowflakes are alike.\n");
	return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值