题目
Eight
*Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 46717 Accepted Submission(s): 11657
Special Judge*Problem Description
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
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.Input
You 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 8is described by this list:
1 2 3 x 4 6 7 5 8
Output
You 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
Source
思路 BFS
这道题算是经典例题了,题目要求我们求给定状态到状态\(123456789x\)的最短路径,由于基于八数码的路径是可逆的,那么问题可以转化为从\(12345678x\)到所有状态的路径,那么我们只需要求一次bfs便可以知道所有的状态,这样对于终点状态不可达的路径我们不会进行多余的计算,这样就减少了时间复杂度。
Code
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#include <utility>
#include <unordered_set>
#include <unordered_map>
#define INF 0x3f3f3f3f
#define IOS ios::sync_with_stdio(false);
#define rep(i, j, k) for(int i = j; i <= k; ++ i)
#define per(i, j, k) for(int i = j; i >= k; -- i)
#define dbg1(a) cout << a << endl;
#define dbg2(a, b) cout << a << " " << b << endl;
#define dbg3(a, b, c) cout << a << " " << b << " " << c << endl;
#define pb(x) push_back(x)
#define eb(x) emplace_back(x)
#define all(x) x.begin(), x.end()
#define f first
#define s second
#define lc p<<1
#define rc p<<1|1
using namespace std;
typedef long long LL;
typedef priority_queue<int, vector<int>, greater<int>> S_HEAP;
typedef priority_queue<int> B_HEAP;
typedef pair<string, int> PSI;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
int dx[] = {0, 1, -1, 0}, dy[] = {1, 0, 0, -1};
char act[] = {'l', 'u', 'd', 'r'};
unordered_map<string, int> d;
string ended = "12345678x";
struct node {
int pre, dir;
node(int PRE, int DIR) {
pre = PRE, DIR = dir;
}
node(){}
}path[N];
void bfs() {
int cnt = 0;
queue<string> q1;
q1.push(ended);
path[cnt].pre = -1;
path[cnt].dir = -1;
d[ended] = cnt ++;
while (q1.size()) {
string t = q1.front(); q1.pop();
int k = t.find('x');
int x = k / 3, y = k % 3;
rep (i, 0, 3) {
int tx = x + dx[i], ty = y + dy[i];
if (tx >= 0 && tx < 3 && ty >= 0 && ty < 3) {
string b = t;
swap(b[k], b[tx * 3 + ty]);
if (d[b])
continue;
q1.push(b);
path[cnt].pre = d[t];
path[cnt].dir = i;
d[b] = cnt++;
}
}
}
}
int main() {
string start;
char c;
bfs();
while (cin >> c) {
start.clear();
start += c;
for (int i = 1; i < 9; i ++) {
cin >> c;
start += c;
}
if (!d[start]) {
puts("unsolvable");
} else {
int k = d[start];
while (k != -1) {
printf("%c", act[path[k].dir]);
k = path[k].pre;
}
cout << endl;
}
}
}