poj3349 snowflake and snowflakes

本文介绍了一种用于比对两组由六个整数组成的序列是否等价的算法。通过构造特殊的哈希表并考虑顺时针及逆时针方向上的序列匹配,实现了对两组数据是否构成相同“雪花”图案的有效判断。

//题意:简化题意后,给你t组数据,每组数据包括6个小于10000000的整数,这6个数围成一个圈,这6个数相同的前提是,例如:1 2 3 4 5 6和3 2 1 6 5 4是一样的,其实意思只要围成的圈是一样的就行,圈相同说明每一个数字相邻的两个数字肯定相同(想象一下类似循环队列的那个圈)。当然有很多种情况,只要有两个数列围成的圈相同就输出相同,都不相同输出都不相同。

//思路:此题转化到判断序列的排序问题,那么想象一下,要判断两个圈相同只需要判断6个数字,按照某种顺序都相同即可,那么枚举出来,假设有两个圈分别为c1, c2,那么首先按照顺时针枚举,这样枚举:c1[0]~c1[5]与c2[0]~c2[5]若都相同则相同,若不相同,下次枚举c1[0]~c1[5]与c2[1],c2[2],c2[3],c2[4],c2[5],c2[0],一次类推,共枚举36个按照顺时针;其次按照逆时针枚举36个,这样枚举:c1[0]~c1[5]与c2[0],c2[5],c2[4],c2[3],c2[2],c2[1];c2[1],c2[0],c2[5],c2[4],c2[3],c2[2]以此类推。

//3584K	2891MS
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int data[100010][6];
int h[150000];

int hash_k(int i)
{
    int sum = 0;
    for(int j = 0; j < 6; j++){
        sum += data[i][j]%149999;
        sum %= 149999;
    }
    return sum;
}

bool cmp(int l, int n)
{
    for(int i = 0; i < 6; i++){
        bool eq = true;
        for(int j = 0; j < 6; j++){
            if(data[l][j] != data[n][(i+j)%6]){
                eq = false;
                break;
            }
        }
        if(eq)
            return true;
    }
    for(int i = 12; i >=7; i--){
        bool eq = true;
        for(int j = 0; j < 6; j++){
            if(data[l][j] != data[n][(i-j)%6]){
                eq = false;
                break;
            }
        }
        if(eq)
            return true;
    }
    return  false;
}

int main()
{
    int key, keyy, t;
    int n ;
    scanf("%d", &n);
    bool ok = false, isT = false;
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < 6; j++){//这里输入按照字符输入,改为getchar此题只需300ms即可
            scanf("%d", &data[i][j]);
        }
        key = hash_k(i);
        keyy = key;
        t = 1;
        while(h[keyy] != 0){
            ok = cmp(h[keyy], i);
            if(ok){
                printf("Twin snowflakes found.\n");
                isT = true;
                break;
            }
            keyy = (key + t*t)%149999;//这是见表的一个公式,不唯一
            t++;
        }
        h[keyy] = i;
    }
    if(!isT)
        printf("No two snowflakes are alike.\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值