首页 > 学院 > 开发设计 > 正文

POJ - 3349 Snowflake Snow Snowflakes解题报告

2019-11-08 02:43:07
字体:
来源:转载
供稿:网友
题目大意: 给你n(100,000)组数,每组6个,每个数都在0-10,000,000范围内,每组数都可以围成一个圈,问你是否可能围成相同的圈(6个数按所给顺序依次相连,可逆时针可顺时针)。如:123456和432156为同一个圈。注意这道题给的时间是4s。

哈希表好像远比我想象的要复杂得多啊 @_@~ loading。。。。 

又过了很久,大概看懂了一点这个哈希表是个什么意思:

对于这道题,我要做的就是,根据每个雪花的六个数(把他们映射到一个整数),把这些雪花分类,尽量多的分类,每一类里的雪花数量尽量少(在内存大小允许的前提下)。而且对于一个已知六条边长度的雪花,都是可以瞬间(以O(1)的时间复杂度)找到这个雪花应该在的类。然后就是如果有多个雪花的六个数都有相同的映射,一个很巧妙很巧妙的方法,现在想想之前的邻接表代码实现看不懂应该也是用了这个方法,就是用next数组表示同一类里面,第i个雪花的下一雪花的标号next[i];

关于这个映射方法:

去网上看了几个映射方法,然后因为第一次做哈希表的题,所有都没用过。现在暂时只讨论本题,因为我要考虑的是这六个数的围成的圈是否有重复的,所有这个映射方法至少应该满足的条件是:有可能围城相同的环的两组数一定要分到一个类里面。换句话说,就是不同组里面的两组数一定不可能围成相同的环。但是如何在满足这个的条件下使得每一类里面的数尽可能的少呢?也就是映射的尽量均匀。

#include<iostream>#include<string.h>#include<stdio.h>#define N 1000000using namespace std;int hash[N+500]={0};int next[N+500]={0};int snow[100500][6]={0};int n;void input(){	for(int i=1;i<=n;i++)	{		for(int j=0;j<6;j++)		{			scanf("%d",&snow[i][j]);		}	}}bool compare(int *a,int *b)//判断a数组和b数组是否可以围成相同的圈 {	for(int i=0;i<6;i++)	{		bool flag=1;		for(int j=0;j<6;j++)		{			if(a[j]!=b[(j+i)%6])			{				flag=0;break;			}		}		if(flag==1)return 1;	}	for(int i=0;i<6;i++)	{		bool flag=1;		for(int j=0;j<6;j++)		{			if(a[j]!=b[(i-j+5)%6])			{				flag=0;break;			}		}		if(flag==1)return 1;	}	return 0;}/*bool compare(int a,int b)//网友的compare函数 {    int i,j,k;    for(i=0;i<6;i++)    {        for(j=i,k=0;k<6;k++,j=(j+1)%6)//???,???????            if(snow[a][k]!=snow[b][j])break;        if(k==6)return true;        for(j=i,k=0;k<6;k++,j=(j+5)%6)//???            if(snow[a][k]!=snow[b][j])break;        if(k==6)return true;    }    return false;}*/int main(){	while(cin>>n)	{		input();		bool flag=0;		memset(hash,0,sizeof(hash));		memset(next,0,sizeof(next));		for(int i=1;i<=n;i++)		{			int x=0; 			for(int j=0;j<6;j++)//求出i对应的x 			{				x=(int)((x+(long long int)snow[i][j]*(long long int)snow[i][j])%N);			}			int l=hash[x];			//cout<<x<<endl;			while(l)//判断是否有与第i个相同的雪花 			{				if(compare(snow[i],snow[l]))				{					flag=1;					break;				}				l=next[l];			}			if(flag==1)break;			//把第i个加入类中 			next[i]=hash[x];			hash[x]=i;		}		if(flag==1)cout<<"Twin snowflakes found."<<endl;		else cout<<"No two snowflakes are alike."<<endl;	}}另外x=(x+snow[i][j]*snow[i][j])%N会runtime error。一定要强制类型转换成long long int。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表