[poj3349]Snowflake Snow Snowflakes_hash
Snowflake Snow Snowflakes poj-3349
题目大意:给出n片雪花,每片雪花有6个角,每个角有一个权值。如果两片雪花中能够各选出一个点,使得从该点顺时针或者逆时针转,得到的权值序列完全相符,那么我们就说这两片雪花是完全相同的。
注释:$1\le n\le 10^5$。
想法:其实并不是一道真正意义上的hash。我们对每个雪花进行处理:如果两个雪花a,b,满足:
$\sum\limits_{i=1}^{6} a_i+\prod\limits_{i=1}^{6}a_i$相等,我们就说这两片雪花是相等的。
之后,用链表遍历上述值相等的雪花即可,这道题我们选择在线处理(orz lyd)。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #define SIZE 100010 #define mod 49999 using namespace std; typedef long long ll; int snow[SIZE][6],head[SIZE],nxt[SIZE]; int n; int Hash(int *a) { int sum=0,mul=1; for(int i=0;i<6;i++) { sum=(sum+a[i])%mod; mul=(ll)mul*a[i]%mod; } return (sum+mul)%mod; } bool equal(int *a,int *b) { for(int i=0;i<6;i++) { for(int j=0;j<6;j++) { bool flag=1; for(int k=0;k<6;k++) { if(a[(i+k)%6]!=b[(j+k)%6]) flag=false; } if(flag) return true; flag=true; for(int k=0;k<6;k++) { if(a[(i+k)%6]!=b[(j-k+6)%6]) flag=false; } if(flag) return true; } } return false; } int tot; bool insert(int *a) { int val=Hash(a); for(int i=head[val];i;i=nxt[i]) { if(equal(snow[i],a)) return true; } ++tot; memcpy(snow[tot],a,6*sizeof(int)); nxt[tot]=head[val]; head[val]=tot; return false; } 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."); return 0; }
小结:hash好强啊,精髓在于将字符串等价成整数,所以方便处理。
| 欢迎来原网站坐坐! >原文链接<