137 雪花雪花雪花

思路 :题目有两种操作方法,一种为旋转,一种为翻转。两种都取最小字典序的排列,取最小。

对比每个雪花的最小字典序相同则雪花相同。

所用技巧:

哈希表——将雪花相同映射为最小字典序相同(最小字典序是唯一的其相同则雪花相同)

求最小字典序的简易方法即代码中的get_min.

取两指针j = 1 ,i = 0偏移值k = 0。欲求a数组的最小字典序即将两个a数组拼接在一起形成一个b数组前六个中不管从哪个开始就类比于旋转。当a[i] == a[j]时偏移量加一直到有一方较大。较大者偏移量前的都不会取到i += k + 1。如果偏移量 == n则全数组相等。直到i == 6 || j == 6

最后取min(i, j)

代码如下:

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 1e5 + 10;
int snows[N][6], idx[N];

void get_min(int a[]){
    static int b[12];
    for(int i = 0;i < 12;i ++) b[i] = a[i % 6];
    int i = 0, j = 1, k; 
    while(i < 6 && j < 6){
        for(k = 0;k < 6 && b[i + k] == b[j + k]; k ++)
        if(k == 6) break;
        if(b[i + k] < b[j + k]){
            j += k + 1;
           
        else{
            i += k + 1;
        }
        if(i == j) i ++;//将i于j错位
    }
    k = min(i, j);
    for(int i = 0;i < 6;i ++){
        a[i] = b[i + k];
    }
}
bool cmp(int a[],int b[]){
    for(int i = 0;i < 6;i ++){
        if(a[i] < b[i]) return true;
        if(a[i] > b[i]) return false;
    }
    return false;
}
bool cmp2(int a, int b){
    for(int i = 0;i < 6;i ++){
        if(snows[a][i] < snows[b][i]) return true;
        if(snows[a][i] > snows[b][i]) return false;
    }
    return false;
}
int main(){
    int n;
    int snow[6], isnow[6];
    scanf("%d",&n);
    for(int i = 0; i < n; i ++){
        for(int j = 0;j < 6; j ++){
        scanf("%d", &snow[j]);
        isnow[5 - j] = snow[j];
        }
        get_min(snow);
        get_min(isnow);
        if(cmp(snow, isnow)) memcpy(snows[i], snow, sizeof snow);
        else memcpy(snows[i], isnow, sizeof isnow);
        idx[i] = i;// 开这个的用处在于可以使用sort排序二维数组
    }
    sort(idx, idx + n, cmp2);
    for(int i = 1;i < n;i ++){
        if(!cmp2(idx[i], idx[i - 1]) && !cmp2(idx[i - 1], idx[i])){
            puts("Twin snowflakes found.");
            return 0;
        }
    }
    puts("No two snowflakes are alike.");
    return 0;

}

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值