ZOJ 2477 Magic Cube(魔方)

ZOJ 2477 Magic Cube(魔方)

Time Limit: 2 Seconds      Memory Limit: 65536 KB

  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:

这是个有名的儿童游戏。游戏中有个方块,由3*3*3的小方块组成。我们可以把方块展开如下:
CN

 

      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.

这些小写字母表示小方块的颜色。比如,’r’为红,’g’为绿,’y’为黄...游戏目标为通过旋转某面方块使得每面只有一种颜色。注意,方块上仅有6种颜色,并且在游戏的任意时刻都有9个准确的矩形。

你知道如何旋转否?我想大部分人都懂,然而还是要讲一讲。某面旋转后,将改变所有相邻面的颜色。如上述立方体,顺时针旋转绿色面后,’w’面的最后一行将变成’b’面的左列,’b’面的左列将变成’y’面的顶行,以此类推。你或许知道从乱序变为最终状态是相当有挑战性的。

此问题中,给定一个方块,要求寻找一种到达最终状态的方法。为了降低难度,必须步骤数不超过5。
CN

 

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:

输入的第一行为一个整数,表示测试用例的数量。每个测试用例10行。
第一行为空行。随后9行为魔方配置。格式参照输入样例。简单起见,每面索引如下:
CN
    /---\
    |   |
    | 4 |
    |   |
/---+---+---+---\
|   |   |   |   |
| 0 | 1 | 2 | 3 |
|   |   |   |   |
\---+---+---+---/
    |   |
    | 5 |
    |   |
    \---/

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

注意两个相邻小写字母间有一个空格。
CN

 

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.

对于每个测试用例,第一行输出到达成功位置的最小步骤数N。若5步内无法到达则输出-1。
随后N行输出每个具体步骤。每个步骤包含两个整数,第一个表示面索引,第二个表示方向。1表示顺时针,且-1表示逆时针。
如果给定配置则为成功位置,输出0。若存多解,择一即可。
CN

 

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

 

题解

  IDA*,据说暴力也是可以的。

  水平太渣没想到什么高明的代价估计方法,取每面不符合的颜色种类数为旋转代价,上限为3。

 

代码 C++

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define MX 54
 5 int maxDeep, n, mp[300], data[MX], opt[5][2],
 6 chgs[6][9] = {
 7     9, 10, 11, 23, 35, 34, 33, 21, 22,
 8     12, 13, 14, 26, 38, 37, 36, 24, 25,
 9     15, 16, 17, 29, 41, 40, 39, 27, 28,
10     18, 19, 20, 32, 44, 43, 42, 30, 31,
11     0, 1, 2, 5, 8, 7, 6, 3, 4,
12     45, 46, 47, 50, 53, 52, 51, 48, 49
13 }, chge[6][12] = {
14     44, 32, 20, 0, 3, 6, 12, 24, 36, 45, 48, 51,
15     35, 23, 11, 6, 7, 8, 15, 27, 39, 47, 46, 45,
16     38, 26, 14, 8, 5, 2, 18, 30, 42, 53, 50, 47,
17     41, 29, 17, 2, 1, 0, 9, 21, 33, 51, 52, 53,
18     11, 10, 9, 20, 19, 18, 17, 16, 15, 14, 13, 12,
19     33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44
20 };
21 int vle() {
22     int rtn = 0, i, j, tmp[6], siz;
23     for (i = 0; i < 6; ++i) {
24         memset(tmp, 0, sizeof tmp); siz = -1;
25         for (j = 0; j < 9; ++j) ++tmp[data[chgs[i][j]]];
26         for (j = 0; j < 6; ++j) if (tmp[j]) ++siz;
27         rtn = std::max(rtn, siz>3 ? 3 : siz);
28     }
29     return rtn;
30 }
31 void chg(int n, int drc) {
32     int i, tmpe[15], tmps[15];
33     if (~drc) {
34         memcpy(tmpe + 3, chge[n], sizeof chge[n]); memcpy(tmps + 2, chgs[n], sizeof chgs[n]);
35         memcpy(tmpe, tmpe + 12, sizeof(int)* 3); memcpy(tmps, tmps + 8, sizeof(int)* 2);
36     }
37     else {
38         memcpy(tmpe, &chge[n][3], sizeof(int)* 9); memcpy(tmps, &chgs[n][2], sizeof(int)* 6);
39         memcpy(tmpe + 9, chge[n], sizeof(int)* 3); memcpy(tmps + 6, chgs[n], sizeof(int)* 2);
40     }
41     for (i = 0; i < 12; ++i) tmpe[i] = data[tmpe[i]];
42     for (i = 0; i < 12; ++i) data[chge[n][i]] = tmpe[i];
43     for (i = 0; i < 8; ++i) tmps[i] = data[tmps[i]];
44     for (i = 0; i < 8; ++i) data[chgs[n][i]] = tmps[i];
45 }
46 
47 bool DFS(int deep) {
48     int i = vle();
49     if (i + deep>maxDeep) return 0;
50     if (!i) return 1;
51     for (i = 0; i < 6; ++i) {
52         chg(opt[deep][0] = i, opt[deep][1] = 1);
53         if (DFS(deep + 1)) return 1;
54         chg(i, -1);
55         chg(opt[deep][0] = i, opt[deep][1] = -1);
56         if (DFS(deep + 1)) return 1;
57         chg(i, 1);
58     }
59     return 0;
60 }
61 
62 int main() {
63     mp['w'] = 0; mp['r'] = 1; mp['g'] = 2; mp['b'] = 3; mp['o'] = 4; mp['y'] = 5;
64     int t, i;
65     char c;
66     scanf("%d", &t);
67     while (t--) {
68         for (i = 0; i < MX; ++i) {
69             scanf(" %c", &c); data[i] = mp[c];
70         }
71         for (maxDeep = vle(); maxDeep < 6 && !DFS(0); ++maxDeep);
72         if (maxDeep < 6) {
73             printf("%d\n", maxDeep);
74             for (i = 0; i < maxDeep; ++i) printf("%d %d\n", opt[i][0], opt[i][1]);
75         }
76         else puts("-1");
77     }
78     return 0;
79 }

 

 

posted @ 2017-06-04 18:03  Simon_X  阅读(434)  评论(1编辑  收藏  举报