POJ-3349 Snowflake Snow Snowflakes(哈希表的数字分析法构造+链地址法处理冲突)

POJ-3349 Snowflake Snow Snowflakes(哈希表的数字分析法构造+链地址法处理冲突)


借鉴地址:https://blog.youkuaiyun.com/lyy289065406/article/details/6647351


SnowflakeSnowSnowflakes
Time Limit: 4000MS Memory Limit: 65536K
   

Description

You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Your program will read information about a collection of snowflakes, and search for a pair that may be identical. Each snowflake has six arms. For each snowflake, your program will be provided with a measurement of the length of each of the six arms. Any pair of snowflakes which have the same lengths of corresponding arms should be flagged by your program as possibly identical.

Input

The first line of input will contain a single integer n, 0 < n ≤ 100000, the number of snowflakes to follow. This will be followed by n lines, each describing a snowflake. Each snowflake will be described by a line containing six integers (each integer is at least 0 and less than 10000000), the lengths of the arms of the snow ake. The lengths of the arms will be given in order around the snowflake (either clockwise or counterclockwise), but they may begin with any of the six arms. For example, the same snowflake could be described as 1 2 3 4 5 6 or 4 3 2 1 6 5.

Output

If all of the snowflakes are distinct, your program should print the message:
No two snowflakes are alike.
If there is a pair of possibly identical snow akes, your program should print the message:
Twin snowflakes found.

Sample Input

2
1 2 3 4 5 6
4 3 2 1 6 5

Sample Output

Twin snowflakes found.

Source


#include<iostream>
#include<stdlib.h>
#include<cstdio>
#include<string.h>
using namespace std;
#define prime 999983
struct Node1
{
   long long len[6];
}snowflake[100001];
typedef struct Node2
{
    long long len[6];            //记录6瓣叶子的长度信息
    Node2* next;
}HashTable;
HashTable* Hash[prime+1];        //我的以后统一:HashTable 是 类的名字 ,Hash 是数组的名字。
                                //这个是构造哈希函数的另一种方法吧,姑且也叫数字分析法吧
long long compute_key(int k)
{
    int i;
    long long key=0;
    for(i=0;i<6;i++)
    {
        key+=(snowflake[k].len[i]) % prime;
        key%=prime;   //利用同余模定理计算key,避免出现大数
    }
    return ++key;    //键值后移1位,把key的范围从0~999982变为 1~999983
}
/*顺时针的话就往后推1个,逆时针的话就往前推1个*/
/*转圈圈的话肯定是要取余的啊*/

/*从顺时针方向判断两片雪花是否相同*/
bool clockwise(HashTable* p,int k)
{
    int i,j;
    for(j=0;j<6;j++)       //顺时针转动j格
    {
        bool flag=true;
        for( i=0;i<6;i++)
        if(snowflake[k].len[i] != p->len[(i+j)%6])
        {
                flag=false;
                break;
        }
        if(flag)
        return true;
    }
    return false;
}

/*从逆时针方向判断两片雪花是否相同*/

bool counterclockwise(HashTable* p,int k)
{
    int i,j;
    for(j=5;j>=0;j--)     //逆时针转动j格
    {
        bool flag=true;
        for(i=0;i<6;i++)
        if(snowflake[k].len[i] != p->len[(5-i-j+6)%6])  //这里+6很漂亮,这样就没有负数的余数问题了
        {                                          //总个数-i就是逆时针的第几个,总个数+i就是顺时针第几个。
            flag=false;
            break;
        }
        if(flag)
        return true;
    }
    return false;
}

/*把第k个雪花信息插入HashTable*/
/*当插入的位置已存在其他雪花信息时,顺便比较*/
bool Hashinsert(int k)
{
    long long key=compute_key(k);
    int i;
    if(Hash[key]==NULL)
    {
        HashTable* temp=(HashTable*)malloc(sizeof(HashTable));
        for(i=0;i<6;i++)
        temp->len[i]=snowflake[k].len[i];
        Hash[key]=temp;      //因为是临时函数,必须保存key对应的地址,不然一切白费
    }
    else                    //用链地址法处理冲突
    {
        HashTable* temp=Hash[key];
        if(clockwise(temp,k)||counterclockwise(temp,k))  //检查雪花是否相同
        return true;
        while(temp->next)       //链地址法就是在相同key值地址后不断连接。
        {
            temp=temp->next;
            if(clockwise(temp,k)||counterclockwise(temp,k))  //检查雪花是否相同
            return true;
        }
        temp=(HashTable*)malloc(sizeof(HashTable));
        for(i=0;i<6;i++)
        temp->len[i]=snowflake[k].len[i];
        temp->next=NULL;
    }
    return false;
}
int main()
{
    int n;
    int i,j;
    scanf("%d",&n);
    int t=n;
    while(t--)
    {
      memset(Hash,0,sizeof(Hash));  // 0 <-> NULL
      bool flag=false;  //记录输入过程中是否出现了相同的雪花
      for(i=1;i<=n;i++)
      {
         for(j=0;j<6;j++)
         scanf("%lld",&snowflake[i].len[j]);
         if(!flag)    //当前还没有出现相同的雪花
         flag=Hashinsert(i);
                    //若出现相同的雪花,则还需后续输入,但不再处理
        }
        if(flag)
        cout<<"Twin snowflakes found."<<endl;
        else
        cout<<"No two snowflakes are alike."<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值