【POJ3349】snowflakes

这是一道可以练习哈希表的模板题。关于哈希表的操作均有涉及。

哈希函数的选取是这道题的关键。这道题的关键字是一个长度为6的序列,并且序列与开始顺序、时钟顺序均无关。
因此,采用哈希函数\(H[x]=\Sigma_{i=0}^5a[i]+\prod_{i=0}^5a[i]\),即:用加和乘的相加来进一步保证散列性。
另外,不能采用带“权值“的哈希函数,因为无序性。
另一个小知识点是顺时针和逆时针的操作,顺时针加 k 取模即可,逆时针正常来说减 k 取模即可,不过可能出现负数,因此再加上6。

代码如下

#include <cstdio>
using namespace std;
const int maxn=1e5+10;
const int mod=1e6+3;

int n,d[6];
struct node{
    int nxt,snow[6];
}t[maxn];
int tot=1,head[mod];

int calc(int p[6]){
    int add=0,mul=1;
    for(int i=0;i<6;i++){
        add=(add+p[i])%mod;
        mul=(long long)mul*p[i]%mod;
    }
    return (add+mul)%mod;
}

bool equal(int a[6],int b[6]){
    for(int i=0;i<6;i++)
        for(int j=0;j<6;j++){
            bool f1=1,f2=1;
            for(int k=0;k<6;k++){
                if(a[(i+k)%6]^b[(j+k)%6])f1=0;
                if(a[(i+k)%6]^b[(j-k+6)%6])f2=0;
            }
            if(f1||f2)return 1;
        }
    return 0;
}

bool insert(int a[6]){
    int u=calc(a);
    for(int i=head[u];i;i=t[i].nxt)
        if(equal(t[i].snow,a))
            return 1;
    ++tot,t[tot].nxt=head[u],head[u]=tot;
    for(int i=0;i<6;i++)t[tot].snow[i]=a[i];
    return 0;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=0;j<6;j++)scanf("%d",&d[j]);
        if(insert(d))return puts("Twin snowflakes found."),0;
    }
    return puts("No two snowflakes are alike."),0;
}

猜你喜欢

转载自www.cnblogs.com/wzj-xhjbk/p/9838581.html