Cantor Expansion (hdu 1430)

Keywords: less

Shortly after the magic cube became popular around the world, Mr. Rubik invented its simplified version, the magic board. The magic board consists of eight blocks of the same size, each of which has a different color and can be represented by numbers 1-8. At any time, the state of the magic board can be expressed by the color sequence of the square: starting from the upper left corner of the magic board, write down the color codes of each block clockwise, and the obtained digital sequence can represent the state of the magic board at this time. For example, a sequence (1, 2, 3, 4, 5, 6, 7, 8) indicates that the magic board state is:

1 2 3 4
8 7 6 5

For the magic board, three different operations can be applied. The specific operation methods are as follows:

A: The upper and lower rows are exchanged, if the above figure can be changed to state 87654321.
B: Each row is rotated to the right at the same time. As shown above, it can be changed to 41236785.
C: Rotate the middle four squares clockwise, as shown above, to 1724368.

Give you the initial state and the target state of the magic board. Give the least number of transformations from the initial state to the visual state. If there are many transformations, choose the one with the lowest dictionary order.

 

Input

Each group of test data consists of two lines, representing the initial state and the visual state of the magic board respectively.

 

Output

For each group of test data output to meet the transformation steps.

 

Sample Input

12345678

17245368

12345678

82754631

 

Sample Output

C

AC

 

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<queue>
using namespace std; 
typedef long long LL;
const int N = 8;
queue <LL> que;
string ans[50000];
char str1[10], str2[10];
bool vis[50000];

int map[10];//mapping
int num[10];
 
LL fac[N];//Factorial
void change(int s[], int o){//o is 0, 1, 2, indicating three changes in ABC
    switch(o){
        case 0:
            for(int i = 0; i < 4; i ++) swap(s[i], s[8-i-1]);
            break;
        case 1:
            for(int i = 3; i >= 1; i --) swap(s[i], s[i-1]);
            for(int i = 4; i < 7; i ++) swap(s[i], s[i+1]);
            break;
        case 2:
            swap(s[1], s[6]);
            swap(s[6], s[5]);
            swap(s[5], s[2]);    
            break;
    } 
} 
void cantor(int s[], LL num, int k){//Cantor expansion, expanding a number num into an array s, k is the length of the array
    int t;
    bool h[k];//0 to k-1, indicating whether it has occurred 
    memset(h, 0, sizeof(h)); 
    for(int i = 0; i < k; i ++){
        t = num / fac[k-i-1];
        num = num % fac[k-i-1];
        for(int j = 0, pos = 0; ; j ++, pos ++){
            if(h[pos]) j --;
            if(j == t){
                h[pos] = true;
                s[i] = pos + 1;
                break;
            }
        }
    }
}
void inv_cantor(int s[], LL &num, int k){//Cantor inverse expansion, converting an array s into a number num 
    int cnt;
    num = 0;
    for(int i = 0; i < k; i ++){
        cnt = 0;
        for(int j = i + 1; j < k; j ++){
            if(s[i] > s[j]) cnt ++;//Judge that several numbers are less than it
        }
        num += fac[k-i-1] * cnt;
    }
}
void init(){
    fac[0] = 1;
    for(int i = 1; i < N; i ++) fac[i] = fac[i-1] * i;
    int a[8], b[8];
    LL temp, temp2;
    que.push(0);
    vis[0] = true;
    while(!que.empty()){
        LL temp = que.front(); que.pop();
        cantor(a, temp, 8);
        for(int i = 0; i < 3; i ++){
            copy(a, a+8, b);
            change(b, i);
            inv_cantor(b, temp2, 8);
            if(!vis[temp2]){
                que.push(temp2);
                vis[temp2] = true;
                ans[temp2] = ans[temp] + (char)('A' + i);
            }
        }
    }
}
int main(){
    init();
    while(~scanf("%s", str1)){
        scanf("%s", str2);
        //First convert all initial states to 12345678
        //The final state is converted according to the transition of the initial state 
        //In this way, only one pretreatment can solve the problem. 
        for(int i = 0; i < 8; i ++) map[str1[i] - '0'] = i + 1;
        for(int i = 0; i < 8; i ++) num[i] = map[str2[i] - '0'];
        LL temp;
        inv_cantor(num, temp, 8);
        cout << ans[temp] << endl;
    }
}

 

Posted by bbaker on Sat, 06 Apr 2019 16:06:30 -0700