Sicily 1151 魔板

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge

Description

 

魔板由8个大小相同方块组成,分别用涂上不同颜色,用18的数字表示。

其初始状态是

1 2 3 4

8 7 6 5

对魔板可进行三种基本操作:

A操作(上下行互换):

8 7 6 5

1 2 3 4

B操作(每次以行循环右移一个):

4 1 2 3

5 8 7 6

C操作(中间四小块顺时针转一格):

1 7 2 4

8 6 3 5

用上述三种基本操作,可将任一种状态装换成另一种状态。

Input

 

输入包括多个要求解的魔板,每个魔板用三行描述。

第一行步数N(可能超过10),表示最多容许的步数。

第二、第三行表示目标状态,按照魔板的形状,颜色用18的表示。

当N等于-1的时候,表示输入结束。

 

Output

 

对于每一个要求解的魔板,输出一行。

首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是ABC),相邻两个操作之间没有任何空格。

注意:如果不能达到,则M输出-1即可。

 

Sample Input

4
5 8 7 6
4 1 2 3
3
8 7 6 5
1 2 3 4
-1

Sample Output

2  AB
1  A

 

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cmath>
  4 using namespace std;
  5 /* 魔板状态结构体 */
  6 struct State {
  7     int x, y;   // 魔板上下两行的状态
  8     string op;  // 从初始状态到达此状态的操作序列
  9     State() {}
 10     State(int a, int b, string str) : x(a), y(b), op(str) {}
 11 } states[50000];
 12 
 13 /* 判断states[index]是否为目标状态 */
 14 bool ok(int x, int y, int index) {
 15     if (states[index].x == x && states[index].y == y)
 16         return true;
 17     return false;
 18 }
 19 
 20 /* 康托展开 , 代码参考百度百科*/ 
 21 /*(n-1)!, 1 <= n <= 8*/
 22 int factory[8] = { 1, 1, 2, 6, 24, 120, 720, 5040};
 23 int cantor(int x) {
 24     int buf[8];
 25     /* 拆成8位, */
 26     for (int i = 0; i < 8; i++) {
 27         int p = (int)pow(10, 7-i);
 28         buf[i] = x / p;
 29         x = x % p;
 30     }
 31     int id = 0;
 32     /* 计算康托展开 */ 
 33     for (int i = 0; i < 8; i++) {
 34       int count = 0;
 35       for (int j = i + 1; j < 8; j++)
 36         if (buf[i] > buf[j]) count++;
 37       id = id + count*factory[8 - 1 - i];
 38     }
 39     return id; 
 40 }
 41 
 42 /*A、B、C操作*/
 43 void A(int &m, int &n, int fp) {
 44     m = states[fp].y;
 45     n = states[fp].x;
 46 }
 47 void B(int &m, int &n, int fp) {
 48     m = (states[fp].x % 10) *1000 + (states[fp].x / 10);
 49     n = (states[fp].y % 10) *1000 + (states[fp].y / 10);
 50 }
 51 void C(int &m, int &n, int fp) {
 52     int i = (states[fp].x / 1000)*1000;
 53     int j = states[fp].x - i;
 54     int a = j / 100; 
 55     int b = (j - a * 100) / 10;
 56     int i1 = (states[fp].y / 1000) * 1000;
 57     int j1 = states[fp].y - i1;
 58     int c = j1 / 100;
 59     int d = (j1 - c * 100) / 10;
 60     m = i + c * 100 + a * 10 + (states[fp].x % 10);
 61     n = i1 + d * 100 + b * 10 + (states[fp].y % 10);
 62 }
 63 
 64 int main() {
 65     int N;
 66     while (cin >> N && N != -1) {
 67         int x = 0, y = 0, temp;  // x,y记录目标魔板状态,temp:临时变量,用于从标准输入流提取数据 
 68         bool flag = false;       // 标志位,true表示到达目标状态,结束搜索  
 69         bool visited[50000];     // 记录魔板是否已被搜索 
 70         for (int i = 0; i < 50000; i++) visited[i] = false; // 初始化为未被搜索,即false。 
 71         for (int i = 0; i < 4; i++) {  // 输入数据 
 72             cin >> temp;
 73             x = x*10 + temp;
 74         }
 75         for (int i = 0; i < 4; i++) {
 76             cin >> temp;
 77             y = y*10 + temp;
 78         } 
 79         if (x == 1234 && y == 8765) flag = true;
 80         /* fp:头指针,即当前处理的魔板下标;rp:尾指针;l: 到达当前状态所用的步数 */
 81         int fp = 0, rp = 0, l = 0;
 82         states[fp] = State(1234, 8765,"");
 83         visited[cantor(12348765)] = true;
 84         while (l < N && !flag) {  //  
 85             int m = states[fp].x;
 86             int n = states[fp].y;
 87             /* A操作,A(int&,int&,int). 参数为引用,所以 m 和 n 的值会被改变, B,C 同理 */ 
 88             A(m, n, fp);
 89             /* 
 90               若操作后状态未被搜索, 则进队,尾指针(下标)加 1。 
 91               同时visited[index]置为true. 
 92               若为目标状态,则标志位置为true,表示找到解,同时结束循环 
 93               B,C同理
 94             */
 95             if (!visited[cantor(m*10000+n)]) {
 96                 states[++rp] = State(m, n, states[fp].op+"A");
 97                 visited[cantor(m*10000+n)] = true;
 98                 if (ok(x, y, rp)) {
 99                     flag = true;
100                     break;
101                 }
102             }
103             B(m, n, fp);
104             if (!visited[cantor(m*10000+n)]) {
105                 states[++rp] = State(m, n, states[fp].op+"B");
106                 visited[cantor(m*10000+n)] = true;
107                 if (ok(x, y, rp)) {
108                     flag = true;
109                     break;
110                 }
111             }
112             C(m, n, fp);
113             if (!visited[cantor(m*10000+n)] ) {
114                 states[++rp] = State(m, n, states[fp].op+"C");
115                 visited[cantor(m*10000+n)] = true;
116                 if (ok(x, y, rp)) {
117                     flag = true;
118                     break;
119                 }
120             }
121             l = states[fp++].op.size(); // 计算到达当前状态需要的步数 然后头指针移到下一位 
122         }
123         if (flag) cout << states[rp].op.size() << " " << states[rp].op << endl;
124         else cout << "-1" << endl;
125     }
126 }
View Code

 

posted on 2015-11-13 11:22  松下风  阅读(135)  评论(0编辑  收藏  举报

导航