1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
InputYou will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
1 2 3
x 4 6
7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
OutputYou will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
1. BFS + 康托展开 + Hash
超时
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXN 15 #define L 663000 #define INF 1000000009 #define eps 0.00000001 /* 八数码问题 解法1.康托展开+Hash+BFS */ struct node { int data[MAXN]; int Hash, pos; vector<char> path; }; int fac[] = { 1,1,2,6,24,120,720,5040,40320 }; int Aim[] = { 1,2,3,4,5,6,7,8,0 }; int beg[MAXN], aim; bool vis[L]; node ans; int Kt(int n, int tmp[]) { int sum = 0, t; for (int i = 0; i < n; i++) { t = 0; for (int j = i + 1; j < n; j++) { if (tmp[j] < tmp[i]) t++; } sum += fac[n - i - 1] * t; } return sum; } bool bfs() { node t; queue<node> q; memcpy(t.data, beg, sizeof(beg)); t.path.clear(); t.Hash = Kt(9, t.data); for (int i = 0; i < 9; i++) if (t.data[i] == 0) t.pos = i; vis[t.Hash] = true; q.push(t); while (!q.empty()) { // cout << 1 << endl; node f = q.front(); q.pop(); if (f.Hash == aim) { ans = f; return true; } if ((f.pos + 1) % 3 != 0) { t = f; swap(t.data[t.pos], t.data[t.pos + 1]); int H = Kt(9, t.data); if (!vis[H]) { vis[H] = true; t.pos = t.pos + 1; t.Hash = H; t.path.push_back('r'); q.push(t); } } if (f.pos % 3 != 0) { t = f; swap(t.data[t.pos], t.data[t.pos - 1]); int H = Kt(9, t.data); if (!vis[H]) { vis[H] = true; t.pos--; t.Hash = H; t.path.push_back('l'); q.push(t); } } if (f.pos > 2) { t = f; swap(t.data[t.pos], t.data[t.pos - 3]); int H = Kt(9, t.data); if (!vis[H]) { vis[H] = true; t.pos = t.pos - 3; t.Hash = H; t.path.push_back('u'); q.push(t); } } if (t.pos < 6) { t = f; swap(t.data[t.pos], t.data[t.pos + 3]); int H = Kt(9, t.data); if (!vis[H]) { vis[H] = true; t.pos = t.pos + 3; t.Hash = H; t.path.push_back('d'); q.push(t); } } } return false; } int main() { aim = Kt(9, Aim); char c[2]; while (scanf("%s", c)) { memset(vis, false, sizeof(vis)); if (c[0] == 'x') beg[0] = 0; else beg[0] = c[0] - '0'; for (int i = 1; i < 9; i++) { scanf("%s", c); if (c[0] == 'x') beg[i] = 0; else beg[i] = c[0] - '0'; } if (bfs()) { for (int i = 0; i < ans.path.size(); i++) { printf("%c", ans.path[i]); } printf(" "); } else printf("unsolvable "); } }
2.
反向打表查询
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXN 363000 #define INF 1000000009 #define eps 0.00000001 /* 反向搜索 打表查询 */ int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}, a; bool vis[MAXN]; vector<char> way[MAXN]; struct node { int pos; int data[10]; int Hash; vector<char> path; }; int Kt(int s[]) { int sum = 0; for (int i = 0; i < 9; i++) { int t = 0; for (int j = i + 1; j < 9; j++) { if (s[j] < s[i]) t++; } sum += fac[8 - i] * t; } return sum + 1; } int x[4] = { 1,-1, 3, -3 }; char d[5] = "lrud"; bool check(int tp, int ti) { if (ti == 0) return (tp + 1) % 3 != 0; else if (ti == 1) return tp % 3 != 0; else if (ti == 2) return tp < 6; else return tp > 2; } void bfs() { int aim[10] = { 1,2,3,4,5,6,7,8,0 }; node t; queue<node> q; memcpy(t.data, aim, sizeof(aim)); t.Hash = Kt(t.data); t.pos = 8; t.path.clear(); vis[t.Hash] = true; a = t.Hash; q.push(t); while (!q.empty()) { node f = q.front(); q.pop(); for (int i = 0; i < 4; i++) { if (!check(f.pos, i)) continue; t = f; int np = t.pos + x[i]; swap(t.data[t.pos], t.data[np]); int H = Kt(t.data); if (!vis[H]) { vis[H] = true; t.pos = np; t.Hash = H; t.path.push_back(d[i]); way[H] = t.path; q.push(t); } } } } int q[11]; int main() { bfs(); char c[2]; while (scanf("%s", c) != EOF) { if (c[0] != 'x') q[0] = c[0] - '0'; else q[0] = 0; for (int i = 1; i < 9; i++) { scanf("%s", c); if (c[0] != 'x') q[i] = c[0] - '0'; else q[i] = 0; } int index = Kt(q); if (index == a) { printf("lr "); continue; } if (way[index].empty()) printf("unsolvable "); else { for (int i = way[index].size() - 1; i >=0; i--) printf("%c", way[index][i]); printf(" "); } } return 0; }