Ac.Wing 137 雪花雪花雪花

该博客讨论了一种使用哈希表解决寻找相同雪花形状的算法。通过定义哈希函数,将雪花的六个元素之和与之积的模运算作为特征值,实现了快速查找。在输入每片雪花后,通过暴力比较所有可能的方向组合来检查是否存在相同的雪花。如果找到,输出'Twinsnowflakesfound.',否则输出'Notwosnowflakesarealike.'。
摘要由CSDN通过智能技术生成

题解:
这个题目应该说是一个比较常规的Hash但是自己太菜了写的好乱QAQ
理一下Hash的思路叭:
首先需要定义一个Hash函数,用来对数据进行离散化操作,然后结合链表去储存数据,一般使用邻接表比较多。理想的一个Hash表可以把算法时间复杂度优化到 O ( 1 ) O(1) O(1),建立Hash函数后我们随即建表,邻接表的表头储存的就是数据的“特征值”,每一个特征值下存着对应的数据链表,这样子我们在查找的时候就可以直接通过特征值找元素了。
那么对于这个题目,我们首先确定Hash函数:对于两个相同的六元组,他们的元素之和,之积都是相同的, 所以我们可以定义 H ( a i , j ) = ( Σ a i , j + ∏ a i , j ) % m o d H(a_{i,j}) = (\Sigma{a_{i,j}} + \prod{a_{i ,j}} )\% mod H(ai,j)=(Σai,j+ai,j)%mod
这样子我们的Hash函数就定义好了。
然后我们每次输入一片雪花,我们都要去查找是否存在和它形状相同相同的雪花,这里我们直接暴力计算即可,因为雪花的角一共只有6个, 6 3 6^3 63的计算量完全OK,但是需要注意的是我们需要比较同向和反向的两种情况,因为它可以按照不同的方向取值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#include<bitset>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define inf -1e12
#define INF 1e12
#define ios std :: ios :: sync_with_stdio(false)
#define PII pair<ll ,ll>

using namespace std;

const int maxn = 1e5 + 10;
const int mode = 99991; //一般选取一个比较大的素数

int head[maxn] = {},Next[maxn] = {},tot = 0,snow[maxn][6]; //注意这里如果二维太大会超内存!

int H(int a[])
{
    ll num = 1,sum = 0;
    for(int i = 0;i < 6;i++){
        sum  = (sum + a[i]) % mode;
        num = (num * a[i]) % mode;
    }
    return (num + sum) % mode;
}

bool equal(int a[],int b[])
{
    int ju = 1;
    for(int i = 0;i < 6;i++){
        for(int j = 0;j < 6;j++){
            ju = 1;
            for(int k = 0;k < 6;k++) if(a[(i + k) % 6] != b[(j + k) % 6]) ju = 0; //同向比较
            if(ju) return 1;
            ju = 1;
            for(int k = 0;k < 6;k++) if(a[(i + k) % 6] != b[(j - k + 6) % 6]) ju = 0; //异向比较
            if(ju) return 1;
        }
    }
    return 0;
}

bool insert(int a[])
{
    ll val = H(a) % mode;
    for(int i = head[val];i;i = Next[i]){
        if(equal(snow[i],a)) return 1;
    }
    tot ++;
    memcpy(snow[tot],a,6 * sizeof(int)); //snow数组里存的对应哈希值,这里的memcpy函数是用来复制数据的
    Next[tot] = head[val]; //头插进表
    head[val] = tot;
    return 0;
}

int main()
{
    ios;
    int n;
    cin >> n;
    for(int k = 0;k < n;k++){
        int a[8];
        for(int i = 0;i < 6;i++) cin >> a[i];
        if(insert(a)){
            cout << "Twin snowflakes found." << endl;
            return 0;
        }
    }
    cout << "No two snowflakes are alike." << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CUCKyrie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值