poj 3349 && 南阳oj 130 Snowflake Snow Snowflakes(相同的雪花)

题意:给你n个六个数的序列,每一个序列代表一朵雪花,问这n个雪花中存不存相同的雪花,若存在输出Twin snowflakes found.,否则输出No two snowflakes are alike.


分析: 在每输入一朵雪花,就在哈希表当中查找是否存在相同雪花,因为雪花可以旋转,所以我们要旋转查找六次,若没有找到则将这多雪花的正反两面插入哈希表中,直到输入结束。这题用在poj上用vector超时,换静态链A了,想偷懒都不行- -!。

刚开始在南阳做的这题,是想旋转查找十二次,只插入正面的雪花,果断TLE;后来旋转查找六次,插入正反两面就A了。之后在poj上一交,再次TLE。。。,把用vector写的哈希表替换成静态链 AC~。

后来想是否可以每次把最小的一个旋转到第一个位置,这样只用查找一次便可以了,改完南阳上AC,poj上WA,想了好久想不明白为什么会WA。经别人提醒发现若存在几个最小值,我只查找一次有些情况是会查找不到的,最后统计出相同最小值的数量cn,然后旋转查找cn次,每次将每个最小值都在第一个位置的情况插入哈希表,最后用时比旋转查找六次稍微少一点。



代码:

#include <iostream>
#include <cstdio>

using namespace std;

struct node{
	int key;
	int v[6];
	int next;
	
	
	node(){}
	
	node(int _key, int *a, int _next){
		key = _key;
		for(int i = 0; i < 6; i++)
			v[i] = a[i];
		next = _next;
	}
};



const int maxn = 100005;
const int mod = 100007;

int n;
int list[mod];//hash表 
node c[maxn*2];//静态链 
int cnt;
int a[6];


void shift(){
	int t = a[0];
	for(int i = 0; i < 5; i++)
		a[i] = a[i+1];
	a[5] = t;
}

void reverse(){
	for(int i = 0; i < 3; i++){
		int  t = a[i];
		a[i] = a[6-i-1];
		a[6-i-1] = t;
	}
}

int hash_key(){
	int sum = 0;
	for(int i = 0; i < 6; i++){
		sum += a[i];
	}
	return sum;
}

void hash_insert(int key, int i){
	int index = key % mod;
	c[i] = node(key,a,list[index]);
	list[index] = i;
}

bool hash_find(int key){
	int index = key % mod;
	for(int i = list[index]; i != -1; i = c[i].next){
		if(c[i].key == key){
			bool f = true;
			for(int j = 0; j < 6; j++){
				if(a[j] != c[i].v[j]){
					f = false; break;
				}
			}
			if(f) return true;
		}
	}
	return false;
}

int main(){
		bool f = false;
		scanf("%d",&n);
		cnt = 0;
		for(int i = 0; i < mod; i++) list[i] = -1;
		
		for(int i = 0; i < n; i++){
			
			for(int j = 0; j < 6; j++)
				scanf("%d",&a[j]);
				
			if(!f){//如果没找到 
				//旋转六次 
				for(int i = 0; i < 6; i++){
					if(hash_find(hash_key())){
						f = true; break;
					}
					shift();
				}
				if(!f) {
					hash_insert(hash_key(),cnt++);
					reverse();//翻转 
					hash_insert(hash_key(),cnt++);
				}
				

				 
			}
		}//end of for i to n
		puts(f?"Twin snowflakes found.":"No two snowflakes are alike.");
	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值