正题
洛谷评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=SP4354
POJ题目链接:http://poj.org/problem?id=3349
题目大意
有n片雪花,他们6个角有不同的长度,如果两片雪花6个角长度相同(可以不同方向),那么就是两片相同的雪花,求第一个相同的雪花。
解题思路
我们可以用hash判断两片雪花是否相同,然后用每片雪花的最小表示法,这样就不需要别的判断。
code
#include<cstdio>
#include<algorithm>
#define ymm 160001
#define ull unsigned long long
int a[21],ans1,ans2,ans,n;
ull h[ymm];
using namespace std;
unsigned hash(ull x){unsigned pos=x%ymm,i=0;while (i<ymm&&h[(pos+i)%ymm]&&h[(pos+i)%ymm]!=x) i++;return (pos+i)%ymm;
}//哈希表
void small()//最小表示法
{int i=7,j=8,k;while(i<=12&&j<=12){for(k=0;k<=6&&a[i+k]==a[j+k];k++);if(k==6) break;if(a[i+k]>a[j+k]){i+=k+1;if(i==j) i++;}else{j+=k+1;if(i==j) j++;}}//正序ans1=min(i,j);i=12,j=11;while(i>=7&&j>=7){for(k=0;k<=6&&a[i-k]==a[j-k];k++);if(k==6) break;if(a[i-k]>a[j-k]){i-=k+1;if(i==j) i--;}else{j-=k+1;if(i==j) j--;}}//逆序ans2=max(i,j);
}
bool insert()
{small();int ans=ans1,x;bool f=false;ull sum=0;int i;for(i=0;i<6&&a[ans1+i]==a[ans2-i];i++);if(a[ans1+i]>a[ans2-i]) ans=ans2,f=true;//求顺时和逆时的最小if(!f)for(i=ans;i<ans+6;i++) sum=sum*13131+a[i];elsefor(i=ans;i>ans-6;i--) sum=sum*13131+a[i];//计算hash值if(h[(x=hash(sum))]==sum) return 1;h[x]=sum;return 0;//判断
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=7;j<=12;j++) scanf("%d",&a[j]),a[j-6]=a[j+6]=a[j];if(insert()){printf("Twin snowflakes found.");return 0;}}printf("No two snowflakes are alike.");
}