ZOJ 2477 Magic Cube

题目描述:

This is a very popular game for children. In this game, there's a cube, which consists of 3 * 3 * 3 small cubes. We can unwrap the cube, it will become like this:

      w w w
      w w w
      w w w
r r r g g g b b b o o o
r r r g g g b b b o o o
r r r g g g b b b o o o
      y y y
      y y y
      y y y

The letters means the color on the small cubes. For example, 'r' means red, 'g' means green, 'y' means yellow....The goal for this game is to rotate the faces of the cube to make each of the faces contains only one color. Note there're exact 6 kind of colors on the cube and there're exact 9 small rectangles totally in any time in the game.

Do you know how to rotate the faces? I think most of you have known it. But I would like to show it again. When a face is rotated, the configuration of colors in all the adjacent faces changes. For the cube above, after we rotate the green face clock-wise, the last line of 'w' face will become the left column of 'b' face, the left column of 'b' face will become the top line of 'y' face, etc. As you may know, reaching the final position from a scrambled configuration can be quite challenging.

In this problem, you are given a configuration of the cube, and asked to give a way to reach the final position. To reduce the difficulty, the steps required will never be greater than 5.


Input

The input contains an integer in the first line, which indicates the number of the test cases. In each test case, there're exact 10 lines. The first line is an empty line. The next 9 lines contain a configuration. The format can be seen in the sample input. For simplicity, we give an index to each face as follows:

    /---\
    |   |
    | 4 |
    |   |
/---+---+---+---\
|   |   |   |   |
| 0 | 1 | 2 | 3 |
|   |   |   |   |
\---+---+---+---/
    |   |
    | 5 |
    |   |
    \---/

Note that there's a space between two adjacent letters.


Output

For each test case, the first line of the output is the smallest count N of the steps to reach the winning position. If the winning position can't be reached in 5 steps, print -1 in this line. Otherwise print each step in one line in the following N lines. A step contains two integers, the first one means the face index, and the second one means the direction. 1 means clock-wise and -1 means counter clock-wise. If the given position is the winning position, print 0 for such test case simply. If there're multiple solutions, any one is acceptable.


Sample Input

2
      w w w
      w w w
      w w w
r r r g g g b b b o o o
r r r g g g b b b o o o
r r r g g g b b b o o o
      y y y
      y y y
      y y y

      w w w
      w w w
      b b b
r r w g g g y b b o o o
r r w g g g y b b o o o
r r w g g g y b b o o o
      r r r
      y y y
      y y y


Sample Output

0
1
1 1

解题报告:

1:本题可以说很考验耐心的一道题,下面代码中pos数组,我搞了三次才没失误,才AC。

2:说下数组的含义:center数组印射每个面中心位置,ans数组保存哪个面被旋转了,dir保存旋转的方向,cube保存魔方的,cubePos数组印射每个面除中心位置的位置,pos数组印射12次操作要怎样改变魔方中位置。

3:重点说下pos数组,假设pos[i][j]代表一个元素,当我们的操作为i 时,如果i为偶数就和下一行交换,为顺时针旋转,反之类似。这里可以用i ^ 1去简化代码。i/2代表我们旋转的是哪一面,因为构造这个数组时就是这样构造的,没有为什么。

4:像 IDA* 算法什么的,可以百度下,蒟蒻也说不清楚=.=。但基本套路都差不多。

5:这里给点我构造pos数组时的过程:

            1  2  3
            4  5  6
            7  8  9

10 11 12    13 14 15   16 17 18   19 20 21
22 23 24    25 26 27   28 29 30   31 32 33
34 35 36    37 38 39   40 41 42   43 44 45

            46 47 48
            49 50 51
            52 53 54
            
            
              第4面
              
            
第0面         第1面     第2面       第3面

            
              第5面

             
             
             37 38 39

       36    46 47 48   40
       35    49 50 51   41
       34    52 53 54   42

             45 44 43

             3  2  1

       18    19 20 21  10
       30    31 32 33  22
       42    43 44 45  34

             54 53 52

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 60;
char cube[N];
ll center[6] = {5, 23, 26, 29, 32, 50}, ans[N], dir[N];
ll cubePos[6][8] = {1, 2, 3, 4, 6, 7, 8, 9,   10, 11, 12, 22, 24, 34, 35, 36,
                    13, 14, 15, 25, 27, 37, 38, 39,   16, 17, 18, 28, 30, 40, 41, 42,
                    19, 20, 21, 31, 33, 43, 44, 45,   46, 47, 48, 49, 51, 52, 53, 54};
ll pos[12][20] = {1 , 4 , 7 , 21, 10, 11, 12, 13, 33, 22, 24, 25, 45, 34, 35, 36, 37, 52, 49, 46,
                  45, 33, 21, 52, 34, 22, 10, 1 , 49, 35, 11, 4 , 46, 36, 24, 12, 7 , 37, 25, 13,
                  7 , 8 , 9 , 12, 13, 14, 15, 16, 24, 25, 27, 28, 36, 37, 38, 39, 40, 46, 47, 48,
                  36, 24, 12, 46, 37, 25, 13, 7 , 47, 38, 14, 8 , 48, 39, 27, 15, 9 , 40, 28, 16,
                  9 , 6 , 3 , 15, 16, 17, 18, 19, 27, 28, 30, 31, 39, 40, 41, 42, 43, 48, 51, 54,
                  39, 27, 15, 48, 40, 28, 16, 9 , 51, 41, 17, 6 , 54, 42, 30, 18, 3 , 43, 31, 19,
                  3 , 2 , 1 , 18, 19, 20, 21, 10, 30, 31, 33, 22, 42, 43, 44, 45, 34, 54, 53, 52,
                  42, 30, 18, 54, 43, 31, 19, 3 , 53, 44, 20, 2 , 52, 45, 33, 21, 1 , 34, 22, 10,
                  21, 20, 19, 10, 1, 2, 3, 18, 11, 4, 6, 17, 12, 7, 8, 9, 16, 13, 14, 15,
                  12, 11, 10, 13, 7, 4, 1, 21, 14, 8, 2, 20, 15, 9, 6, 3, 19, 16, 17, 18,
                  37, 38, 39, 36, 46, 47, 48, 40, 35, 49, 51, 41, 34, 52, 53, 54, 42, 45, 44, 43,
                  34, 35, 36, 45, 52, 49, 46, 37, 44, 53, 47, 38, 43, 54, 51, 48, 39, 42, 41, 40};
bool dfs(ll d, ll maxD){
    ll cnt = 0;
    for(ll i=0; i<6; ++i)
        for(ll j=0; j<8; ++j)
            if(cube[cubePos[i][j]] != cube[center[i]])++cnt;
    if(d + (cnt+11)/12 > maxD)return 0;
    if(cnt == 0)return 1;
    char tool[N];
    for(ll i=0; i<12; ++i){
        memcpy(tool, cube, sizeof(cube));
        for(ll j=0; j<20; ++j)
            cube[pos[i][j]] = tool[pos[i^1][j]];
        ans[d] = i/2;
        dir[d] = (i&1) == 1 ? -1 : 1;
        if(dfs(d+1, maxD))return 1;
        memcpy(cube, tool, sizeof(tool));
    }
    return 0;
}
int main(){
    ll t;
    scanf("%lld", &t);
    while(t--){
        char x[2];
        for(ll i=1; i<=54; ++i)scanf("%s", x), cube[i] = x[0];
        ll maxD = 0;
        for(; !dfs(0, maxD); ++maxD){
            if(maxD > 5)break;
        }
        if(maxD == 0){
            printf("0\n");
            continue;
        }
        if(maxD > 5){
            printf("-1\n");
            continue;
        }
        printf("%lld\n", maxD);
        for(ll i=0; i<maxD; ++i)printf("%lld %lld\n", ans[i], dir[i]);
    }
    return 0;
}
发布了190 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/jun_____/article/details/104253706
ZOJ