题意:
n片雪花,每片雪花的6个角有不同的长度。对于两片雪花,如果从任意一个角开始顺时针比较或逆时针比较,这两片雪花的六个角长度分别相等,则这两片雪花长得一模一样。问这n片雪花中有没有 Twin snowflakes ?
思路:
两片相同的雪花,六个角之和、六个角之积一定都分别相等,定义Hash函数
建立一个Hash表,将n片雪花依次插入。对于第 i 片雪花,直接扫描 val=H(i) 对应的链表 h[val],检查是否存在与 i 相同的雪花即可。
详细请看注释(Hash表的操作重点学习):
#include<iostream>
using namespace std;
typedef long long ll;
const int N=100010;
int n,tot,P=99991;
int snow[N][6],h[N],ne[N];
int H(int *a){
int sum=0,mul=1;
for(int i=0;i<6;++i){
sum=(sum+a[i])%P;
mul=(ll)mul*a[i]%P;
}
return (sum+mul)%P;
}
bool equal(int *a,int *b){
for(int i=0;i<6;++i){
for(int j=0;j<6;++j){
bool eq=1;
for(int k=0;k<6;++k)
if(a[i+k%6]!=b[(j+k)%6]) eq=0;
if(eq)return 1;
eq=1;
for(int k=0;k<6;++k)
if(a[(i+k)%6]!=b[(j-k+6)%6])eq=0;
if(eq)return 1;
}
}
return 0;
}
bool insert(int *a){
int val=H(a);//该雪花的hash函数值val
for(int i=h[val];i;i=ne[i]){//遍历hash值为val的链表(表头h[val])
if(equal(snow[i],a)) return 1;//找到相等的雪花则返回1
}
++tot;//没找到则新插入 //头结点初始是0 //雪花编号从1开始
memcpy(snow[tot],a,6*sizeof(int));//复制该雪花到snow[tot]
ne[tot]=h[val];//tot号雪花的下一片是现在的头结点装的雪花//相当于将tot号雪花 前插 进链表
h[val]=tot;//头结点装tot
return 0;
}
int main(){
cin>>n;
for(int i=1;i<=n;++i){
int a[10];
for(int j=0;j<6;++j) scanf("%d",&a[j]);
if(insert(a)){
puts("Twin snowflakes found.");
return 0;
}
}
puts("No two snowflakes are alike.");
}
本文介绍了一种通过Hash函数和链表实现的高效算法,用于判断多片雪花是否具有完全相同的六个角长度,从而确定是否存在Twinsnowflakes。算法首先计算雪花的六个角长度之和及乘积的Hash值,然后利用Hash表存储并对比这些值,快速找出重复雪花。
689

被折叠的 条评论
为什么被折叠?



