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
题意:还原一个魔方,如果超过5步,输出-1即可,否则输出最快还原步骤。
思路:题意说的不清楚,需要对着样例转一下4面和5面。一顿模拟就好了,想法很简单,但要维护旋转时位置的更替关系,写起来还是比较恶心的,,,用bfs暴力1150ms卡过,正解是IDA*,可以用所有面中不合法的颜色种类数的最大值作为估价函数。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 #define pcv pair<cube, vector<pii> > 31 32 const double pi = acos(-1.0); 33 const int INF = 0x3f3f3f3f; 34 const int MOD = 1e9 + 7; 35 const double EPS = 1e-9; 36 37 struct cube { 38 char a[6][11]; 39 cube rot(int face[], int p[][3]) { 40 cube b; 41 for (int i = 0; i < 6; ++i) { 42 for (int j = 1; j <= 9; ++j) { 43 b.a[i][j] = a[i][j]; 44 } 45 } 46 for (int i = 0; i < 4; ++i) { 47 int _i = (i + 3) % 4; 48 int f = face[i], _f = face[_i]; 49 //cout << f << ' ' << _f << endl; 50 for (int j = 0; j < 3; ++j) { 51 b.a[f][p[i][j]] = a[_f][p[_i][j]]; 52 } 53 } 54 return b; 55 } 56 cube clockwise(int face) { 57 cube b; 58 int f[4], p[4][3]; 59 if (!face) { 60 f[0] = 4, f[1] = 1, f[2] = 5, f[3] = 3; 61 p[0][0] = 1, p[0][1] = 2, p[0][2] = 3; 62 p[1][0] = 7, p[1][1] = 4, p[1][2] = 1; 63 p[2][0] = 9, p[2][1] = 8, p[2][2] = 7; 64 p[3][0] = 3, p[3][1] = 6, p[3][2] = 9; 65 } else if (1 == face) { 66 f[0] = 4, f[1] = 2, f[2] = 5, f[3] = 0; 67 p[0][0] = 1, p[0][1] = 4, p[0][2] = 7; 68 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 69 p[2][0] = 1, p[2][1] = 4, p[2][2] = 7; 70 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 71 } else if (2 == face) { 72 f[0] = 4, f[1] = 3, f[2] = 5, f[3] = 1; 73 p[0][0] = 7, p[0][1] = 8, p[0][2] = 9; 74 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 75 p[2][0] = 3, p[2][1] = 2, p[2][2] = 1; 76 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 77 } else if (3 == face) { 78 f[0] = 4, f[1] = 0, f[2] = 5, f[3] = 2; 79 p[0][0] = 9, p[0][1] = 6, p[0][2] = 3; 80 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 81 p[2][0] = 9, p[2][1] = 6, p[2][2] = 3; 82 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 83 } else if (4 == face) { 84 f[0] = 0, f[1] = 3, f[2] = 2, f[3] = 1; 85 for (int i = 0; i < 4; ++i) { 86 p[i][0] = 3, p[i][1] = 2, p[i][2] = 1; 87 } 88 } else { 89 f[0] = 2, f[1] = 3, f[2] = 0, f[3] = 1; 90 for (int i = 0; i < 4; ++i) { 91 p[i][0] = 7, p[i][1] = 8, p[i][2] = 9; 92 } 93 } 94 b = rot(f, p); 95 b.a[face][1] = a[face][7]; 96 b.a[face][2] = a[face][4]; 97 b.a[face][3] = a[face][1]; 98 b.a[face][4] = a[face][8]; 99 b.a[face][6] = a[face][2]; 100 b.a[face][7] = a[face][9]; 101 b.a[face][8] = a[face][6]; 102 b.a[face][9] = a[face][3]; 103 return b; 104 } 105 bool ok() { 106 for (int i = 0; i < 6; ++i) { 107 char c = a[i][1]; 108 for (int j = 2; j <= 9; ++j) { 109 if (c != a[i][j]) { 110 return false; 111 } 112 } 113 } 114 return true; 115 } 116 }; 117 int T; 118 cube a; 119 void get_a() { 120 vector<char> vec; 121 char c; 122 while (vec.size() < 54) { 123 c = getchar(); 124 if (isalpha(c)) { 125 vec.pb(c); 126 } 127 } 128 for (int i = 0; i < 9; ++i) { 129 a.a[4][i + 1] = vec[i]; 130 } 131 for (int l = 0; l < 3; ++l) { 132 for (int f = 0; f < 4; ++f) { 133 for (int i = 1; i <= 3; ++i) { 134 a.a[f][l * 3 + i] = vec[l * 12 + f * 3 + i + 8]; 135 } 136 } 137 } 138 for (int i = 1; i <= 9; ++i) { 139 a.a[5][i] = vec[44 + i]; 140 } 141 int dir[8] = {1, 2, 3, 6, 9, 8, 7, 4}; 142 int x = a.a[4][dir[7]], y = a.a[4][dir[6]]; 143 for (int i = 7; i > 2; i -= 2) { 144 a.a[4][dir[i]] = a.a[4][dir[i - 2]]; 145 a.a[4][dir[i - 1]] = a.a[4][dir[i - 3]]; 146 } 147 a.a[4][dir[1]] = x; 148 a.a[4][dir[0]] = y; 149 x = a.a[5][dir[0]]; 150 y = a.a[5][dir[1]]; 151 for (int i = 0; i < 5; i += 2) { 152 a.a[5][dir[i]] = a.a[5][dir[i + 2]]; 153 a.a[5][dir[i + 1]] = a.a[5][dir[i + 3]]; 154 } 155 a.a[5][dir[7]] = y; 156 a.a[5][dir[6]] = x; 157 /*for (int i = 0; i < 6; ++i) { 158 for (int j = 1; j <= 9; ++j) { 159 cout << a.a[i][j] << ' '; 160 } 161 cout << endl; 162 }*/ 163 } 164 queue<pcv> que; 165 int main() { 166 scanf("%d", &T); 167 while (T--) { 168 get_a(); 169 while (que.size()) { 170 que.pop(); 171 } 172 vector<pii> vec, ans; 173 que.push(mp(a, vec)); 174 int flag = 0; 175 while (que.size()) { 176 pcv pp = que.front(); que.pop(); 177 cube a = pp.first; 178 vector<pii> vec = pp.second; 179 if (a.ok()) { 180 ans = vec; 181 flag = 1; 182 break; 183 } 184 if (5 == vec.size()) continue; 185 for (int f = 0; f < 6; ++f) { 186 cube b1 = a.clockwise(f); 187 //printf("%d\n", f); pau; 188 vector<pii> vec1 = vec; 189 vec1.pb(mp(f, 1)); 190 que.push(mp(b1, vec1)); 191 cube b2 = b1.clockwise(f).clockwise(f); 192 vector<pii> vec2 = vec; 193 vec2.pb(mp(f, -1)); 194 que.push(mp(b2, vec2)); 195 } 196 } 197 if (flag) { 198 printf("%d\n", ans.size()); 199 for (int i = 0; i < ans.size(); ++i) { 200 int x = ans[i].first, y = ans[i].second; 201 printf("%d %d\n", x, y); 202 } 203 } else { 204 puts("-1"); 205 } 206 } 207 return 0; 208 } 209 /* 210 3 211 w w w 212 w w w 213 w w w 214 r r r g g g b b b o o o 215 r r r g g g b b b o o o 216 r r r g g g b b b o o o 217 y y y 218 y y y 219 y y y 220 221 w w w 222 w w w 223 b b b 224 r r w g g g y b b o o o 225 r r w g g g y b b o o o 226 r r w g g g y b b o o o 227 r r r 228 y y y 229 y y y 230 */
加上估价函数, 试了一下IDA*,跑的果然快,20ms,快了50倍。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 #define pcv pair<cube, vector<pii> > 31 32 const double pi = acos(-1.0); 33 const int INF = 0x3f3f3f3f; 34 const int MOD = 1e9 + 7; 35 const double EPS = 1e-9; 36 37 struct cube { 38 char a[6][11]; 39 cube rot(int face[], int p[][3]) { 40 cube b; 41 for (int i = 0; i < 6; ++i) { 42 for (int j = 1; j <= 9; ++j) { 43 b.a[i][j] = a[i][j]; 44 } 45 } 46 for (int i = 0; i < 4; ++i) { 47 int _i = (i + 3) % 4; 48 int f = face[i], _f = face[_i]; 49 //cout << f << ' ' << _f << endl; 50 for (int j = 0; j < 3; ++j) { 51 b.a[f][p[i][j]] = a[_f][p[_i][j]]; 52 } 53 } 54 return b; 55 } 56 cube clockwise(int face) { 57 cube b; 58 int f[4], p[4][3]; 59 if (!face) { 60 f[0] = 4, f[1] = 1, f[2] = 5, f[3] = 3; 61 p[0][0] = 1, p[0][1] = 2, p[0][2] = 3; 62 p[1][0] = 7, p[1][1] = 4, p[1][2] = 1; 63 p[2][0] = 9, p[2][1] = 8, p[2][2] = 7; 64 p[3][0] = 3, p[3][1] = 6, p[3][2] = 9; 65 } else if (1 == face) { 66 f[0] = 4, f[1] = 2, f[2] = 5, f[3] = 0; 67 p[0][0] = 1, p[0][1] = 4, p[0][2] = 7; 68 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 69 p[2][0] = 1, p[2][1] = 4, p[2][2] = 7; 70 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 71 } else if (2 == face) { 72 f[0] = 4, f[1] = 3, f[2] = 5, f[3] = 1; 73 p[0][0] = 7, p[0][1] = 8, p[0][2] = 9; 74 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 75 p[2][0] = 3, p[2][1] = 2, p[2][2] = 1; 76 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 77 } else if (3 == face) { 78 f[0] = 4, f[1] = 0, f[2] = 5, f[3] = 2; 79 p[0][0] = 9, p[0][1] = 6, p[0][2] = 3; 80 p[1][0] = 1, p[1][1] = 4, p[1][2] = 7; 81 p[2][0] = 9, p[2][1] = 6, p[2][2] = 3; 82 p[3][0] = 9, p[3][1] = 6, p[3][2] = 3; 83 } else if (4 == face) { 84 f[0] = 0, f[1] = 3, f[2] = 2, f[3] = 1; 85 for (int i = 0; i < 4; ++i) { 86 p[i][0] = 3, p[i][1] = 2, p[i][2] = 1; 87 } 88 } else { 89 f[0] = 2, f[1] = 3, f[2] = 0, f[3] = 1; 90 for (int i = 0; i < 4; ++i) { 91 p[i][0] = 7, p[i][1] = 8, p[i][2] = 9; 92 } 93 } 94 b = rot(f, p); 95 b.a[face][1] = a[face][7]; 96 b.a[face][2] = a[face][4]; 97 b.a[face][3] = a[face][1]; 98 b.a[face][4] = a[face][8]; 99 b.a[face][6] = a[face][2]; 100 b.a[face][7] = a[face][9]; 101 b.a[face][8] = a[face][6]; 102 b.a[face][9] = a[face][3]; 103 return b; 104 } 105 bool ok() { 106 for (int i = 0; i < 6; ++i) { 107 char c = a[i][1]; 108 for (int j = 2; j <= 9; ++j) { 109 if (c != a[i][j]) { 110 return false; 111 } 112 } 113 } 114 return true; 115 } 116 int h() { 117 int res = 0; 118 for (int i = 0; i < 6; ++i) { 119 set<char> ss; 120 for (int j = 1; j <= 9; ++j) { 121 ss.insert(a[i][j]); 122 } 123 int siz = ss.size(); 124 if (res < siz) res = siz; 125 } 126 return res; 127 } 128 }; 129 int T; 130 cube a; 131 void get_a() { 132 vector<char> vec; 133 char c; 134 while (vec.size() < 54) { 135 c = getchar(); 136 if (isalpha(c)) { 137 vec.pb(c); 138 } 139 } 140 for (int i = 0; i < 9; ++i) { 141 a.a[4][i + 1] = vec[i]; 142 } 143 for (int l = 0; l < 3; ++l) { 144 for (int f = 0; f < 4; ++f) { 145 for (int i = 1; i <= 3; ++i) { 146 a.a[f][l * 3 + i] = vec[l * 12 + f * 3 + i + 8]; 147 } 148 } 149 } 150 for (int i = 1; i <= 9; ++i) { 151 a.a[5][i] = vec[44 + i]; 152 } 153 int dir[8] = {1, 2, 3, 6, 9, 8, 7, 4}; 154 int x = a.a[4][dir[7]], y = a.a[4][dir[6]]; 155 for (int i = 7; i > 2; i -= 2) { 156 a.a[4][dir[i]] = a.a[4][dir[i - 2]]; 157 a.a[4][dir[i - 1]] = a.a[4][dir[i - 3]]; 158 } 159 a.a[4][dir[1]] = x; 160 a.a[4][dir[0]] = y; 161 x = a.a[5][dir[0]]; 162 y = a.a[5][dir[1]]; 163 for (int i = 0; i < 5; i += 2) { 164 a.a[5][dir[i]] = a.a[5][dir[i + 2]]; 165 a.a[5][dir[i + 1]] = a.a[5][dir[i + 3]]; 166 } 167 a.a[5][dir[7]] = y; 168 a.a[5][dir[6]] = x; 169 /*for (int i = 0; i < 6; ++i) { 170 for (int j = 1; j <= 9; ++j) { 171 cout << a.a[i][j] << ' '; 172 } 173 cout << endl; 174 }*/ 175 } 176 queue<pcv> que; 177 int main() { 178 scanf("%d", &T); 179 while (T--) { 180 get_a(); 181 while (que.size()) { 182 que.pop(); 183 } 184 vector<pii> vec, ans; 185 que.push(mp(a, vec)); 186 int flag = 0; 187 while (que.size()) { 188 pcv pp = que.front(); que.pop(); 189 cube a = pp.first; 190 vector<pii> vec = pp.second; 191 if (a.ok()) { 192 ans = vec; 193 flag = 1; 194 break; 195 } 196 if (a.h() + vec.size() > 6) continue; 197 if (5 == vec.size()) continue; 198 for (int f = 0; f < 6; ++f) { 199 cube b1 = a.clockwise(f); 200 //printf("%d\n", f); pau; 201 vector<pii> vec1 = vec; 202 vec1.pb(mp(f, 1)); 203 que.push(mp(b1, vec1)); 204 cube b2 = b1.clockwise(f).clockwise(f); 205 vector<pii> vec2 = vec; 206 vec2.pb(mp(f, -1)); 207 que.push(mp(b2, vec2)); 208 } 209 } 210 if (flag) { 211 printf("%d\n", ans.size()); 212 for (int i = 0; i < ans.size(); ++i) { 213 int x = ans[i].first, y = ans[i].second; 214 printf("%d %d\n", x, y); 215 } 216 } else { 217 puts("-1"); 218 } 219 } 220 return 0; 221 } 222 /* 223 3 224 w w w 225 w w w 226 w w w 227 r r r g g g b b b o o o 228 r r r g g g b b b o o o 229 r r r g g g b b b o o o 230 y y y 231 y y y 232 y y y 233 234 w w w 235 w w w 236 b b b 237 r r w g g g y b b o o o 238 r r w g g g y b b o o o 239 r r w g g g y b b o o o 240 r r r 241 y y y 242 y y y 243 */