POJ 3349 解题报告

这道题我用的是hash。之前用map TLE了。看discuss发现得用hash。事实是hash要比map快很多。

这里的hash用的是最简单的求和再对一个大prime(999331)取余。

另外用到了数组形式的链表。用一个next数组保存下一个同hash的snowflake的位置。

要对同hash的所有snowflake按照链表一一判断是否相同。这里判断就是老老实实地对不同起点进行遍历,每次都顺时针和逆时针各判断一次。

从discuss的反馈来看,似乎只要6个数相同就可以判断相同了,因而有更快更简单的做法,比如排序。但是应该是与题意不符的。

thestoryofsnow3349Accepted6792K2188MSC++2219B
/* 
ID: thestor1 
LANG: C++ 
TASK: poj3349 
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

const int MAXN = 100000;
const int MOD =  999331;

bool cmp(int snowflake1[], int snowflake2[])
{
	int min1 = *min_element(snowflake1, snowflake1 + 6);
	int max1 = *max_element(snowflake1, snowflake1 + 6);

	int min2 = *min_element(snowflake2, snowflake2 + 6);
	int max2 = *max_element(snowflake2, snowflake2 + 6);

	if (min1 != min2 || max1 != max2)
	{
		return false;
	}

	bool same = false;
	for (int i = 0; i < 6; ++i)
	{
		// clockwise
		int j = 0;
		for (j = 0; j < 6; ++j)
		{
			if (snowflake1[(i + j) % 6] != snowflake2[j])
			{
				break;
			}
		}
		if (j == 6)
		{
			same = true;
			break;
		}

		// counterclockwise
		j = 0;
		for (j = 0; j < 6; ++j)
		{
			if (snowflake1[(i - j + 6) % 6] != snowflake2[j])
			{
				break;
			}
		}
		if (j == 6)
		{
			same = true;
			break;
		}
	}

	return same;
}


int main()
{
	int snowflakes[MAXN][6];
	int next[MAXN];
	
	int starters[MAXN * 10];
	memset(starters, -1, MAXN * 10 * sizeof(int));

	int n;
	scanf("%d", &n);
	bool duplicate = false;
	for (int i = 0; i < n; ++i)
	{
		next[i] = -1;
		for (int j = 0; j < 6; ++j)
		{
			scanf("%d", &snowflakes[i][j]);
		}

		if (duplicate)
		{
			continue;
		}
		
		int hashval = 0;
		for (int j = 0; j < 6; ++j)
		{
			hashval += snowflakes[i][j];
		}
		hashval %= MOD;

		if (starters[hashval] == -1)
		{
			starters[hashval] = i;
		}
		else
		{
			int starter = starters[hashval];
			while (starter != -1)
			{
				if (cmp(snowflakes[i], snowflakes[starter]))
				{
					duplicate = true;
					break;
				}
				starter = next[starter];
			}

			next[i] = starters[hashval];
			starters[hashval] = i;
		}
	}

	if (!duplicate)
	{
		printf("No two snowflakes are alike.\n");
	}
	else
	{
		printf("Twin snowflakes found.\n");
	}

	return 0;  
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值