Advanced Guide to Algorithm Competition---0x14 (hash) Snowflake Snow Snowflakes

Topic

Insert picture description here
Insert picture description here

Input sample

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

Sample output

Twin snowflakes found.

Problem solution (minimal notation)

  1. Give you the length of the six corners of N pieces of snowflakes, and then ask you whether there are two pieces of the same shape in these N pieces of snowflakes. The most direct way is to enumerate violently. However, considering the flip and change, violence is unrealistic. We It can be done with a hash, and a hash value can be used to represent each snowflake. When the two hash values ​​are equal, it means that the two snowflakes are the same. Obviously, for snowflakes with the same shape, the sum of their hexagonal lengths, The product of length is equal, then we add its sum and product to modulo a larger prime number to represent its hash value
  2. For this question, we adopt a better method to improve the efficiency of judging whether the shape of two snowflakes are the same.That is the definition of the minimum representation of a cyclic isomorphic string: a sequence of length n is rotated n times, and the smallest lexicographical order among these n sequences is the smallest representation For example, the smallest representation of 4 3 2 1 6 5 is 1 6 5 4 3 2
  3. For this question, there are two operation methods, one is flipping, the other is moving, that is, 1 2 3 4 5 6 can be flipped to 6 5 4 3 2 1, or 5 4 3 2 1 6 can be moved, and continue to move 4 3 2 1 6 5 We take a minimum representation of the two times before and after the flip as the unique identifier of this snowflake, then if there is the same minimum representation, we consider the two snowflakes to be the same
  4. Detailed explanation of minimum notation-----> Click here , it will skip by itself

Code

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1e5 + 10;


int n;
int snows[N][6], idx[N];


//最小表示模板
void get_min(int *b) {
    
    

    int a[12];
    for (int i = 0; i < 12; i++) a[i] = b[i % 6];

    int i = 0, j = 1, k;
    while (i < 6 && j < 6) {
    
    
        for (k = 0; k < 6 && a[i + k] == a[j + k]; k++);
        if (k == 6) break;

        if (a[i + k] > a[j + k]) {
    
    
            i += k + 1;
            if (i == j) i++;
        } else {
    
    
            j += k + 1;
            if (i == j) j++;
        }
    }

    k = min(i, j);
    for (i = 0; i < 6; i++) b[i] = a[i + k];
}

bool cmp1(int a[], int b[]) {
    
    

    for (int i = 0; i < 6; i++) {
    
    
        if (a[i] < b[i]) {
    
    
            return true;
        } else 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;
        } else if (snows[a][i] > snows[b][i]) {
    
    
            return false;
        }
    }
    return false;
}

int main() {
    
    

    cin >> n;
    int snow[6], isnow[6];
    for (int i = 0; i < n; i++) {
    
    
        for (int j = 0, k = 5; j < 6; j++, k--) {
    
    
            cin >> snow[j];
            isnow[k] = snow[j];
        }
        get_min(snow);
        get_min(isnow);
        //求出两个最小表示取其最小
        if (cmp1(snow, isnow)) memcpy(snows[i], snow, sizeof snow);
        else memcpy(snows[i], isnow, sizeof isnow);
        idx[i] = i;
    }

    sort(idx, idx + n, cmp2);

    bool flag = false;
    for (int i = 1; i < n; i++) {
    
       //判断是否有相同的最小表示
        if (!cmp2(idx[i], idx[i - 1]) && !cmp2(idx[i - 1], idx[i])) {
    
    
            flag = true;
            break;
        }
    }
    if (flag) cout << "Twin snowflakes found." << endl;
    else cout << "No two snowflakes are alike." << endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_44791484/article/details/113804146