Sicily 1151 魔板
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge
Description
魔板由8个大小相同方块组成,分别用涂上不同颜色,用1到8的数字表示。
其初始状态是
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),表示最多容许的步数。
第二、第三行表示目标状态,按照魔板的形状,颜色用1到8的表示。
当N等于-1的时候,表示输入结束。
Output
对于每一个要求解的魔板,输出一行。
首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是A、B或C),相邻两个操作之间没有任何空格。
注意:如果不能达到,则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 }