poj3349(哈希+链地址法)

给出N个六边形的6个边长,问其中是否有完全相同的两个六边形,完全相同包括边的长度和位置都要相同。边给出的顺序是逆时针或者顺时针的。

给每个6边形一个哈希值,方法是对6条边长度的平方和取模

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e6;
const int mod = 999983;//100W以内的大素数
typedef long long LL;

int n;
char s[100010][10];
int hash[maxn],next[maxn];

bool judge(int a,int b)
{
    int i,j,k;
    for(i = 0; i < 6; ++i)//串的起始位置
    {
        for(j = i,k = 0; k < 6; ++k,j = (j+1)%6)//顺时针
            if(s[a][k] != s[b][j]) break;
        if(k == 6) return true;
        for(j = i,k = 0; k < 6; ++k, j = (j+5)%6)//逆时针
            if(s[a][k] != s[b][j]) break;
        if(k == 6) return true;
    }
    return false;
}

int main()
{
    //freopen("in","r",stdin);
    scanf("%d",&n);
    bool flag = false;
    for(int i = 1; i <= n; ++i)
    {
        int x = 0,u;
        for(int j = 0; j < 6; ++j)
        {
            scanf("%d",&s[i][j]);
            x = (int)((x+(LL)s[i][j]*(LL)s[i][j])%mod);//防止溢出
        }
        u = hash[x];//hash【】里面存的是哈希值对应的某一行的行号
        while(u){
            if(judge(i,u)) {flag = true;break;}//只要u!=0,说明之前出现过这个hash值,则可能出现相同的六边形,判断一下
            u = next[u];//沿着“链表”往下走
        }
        if(flag)break;
        next[i] = hash[x];//类似链表的插入方法,把hash值相同的放在一起,方便以后用next可以遍历到所有hash相同的边
        hash[x] = i;//更新表头
    }
    if(flag) printf("Twin snowflakes found.
");
    else printf("No two snowflakes are alike.
");
}
原文地址:https://www.cnblogs.com/Norlan/p/4747209.html