Eight
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 29854 | Accepted: 12989 | Special Judge |
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 a description of a configuration of the 8 puzzle. The 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
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.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
1.广搜,打表
从终点反向广搜,记录能够到达的所有点,打表.(hdu上109ms)
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define maxn 400005
using namespace std;
struct Node{
char p[10];
int x, y, f;
char ch;
}node[maxn];
int vis[maxn], d[10];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int k[4] = {'u', 'd', 'l', 'r'}, m = 1;
int cal(char *p){
int ans = 0;
for(int i = 0; i < 9; i++){
int h = 0;
for(int j = i+1; j < 9; j++)
if(p[i] > p[j])
h++;
ans += h * d[8-i];
}
return ans;
}
void Bfs(){
char t[10] = "123456780";
vis[cal(t)] = 1;
strcpy(node[1].p, t);
node[1].x = 2, node[1].y = 2;
node[1].f = -1;
queue<int> q;
q.push(1);
while(!q.empty()){
int h = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int x = node[h].x + dir[i][0];
int y = node[h].y + dir[i][1];
if(x >= 0 && x < 3 && y >= 0 && y < 3){
strcpy(t, node[h].p);
swap(t[node[h].x*3+node[h].y], t[x*3+y]);
int e = cal(t);
if(vis[e] == 0){
++m;
vis[e] = m;
strcpy(node[m].p, t);
node[m].x = x;
node[m].y = y;
node[m].ch = k[i];
node[m].f = h;
q.push(m);
}
}
}
}
}
void print(int e){
vector<char> v;
while(node[e].f != -1){
v.push_back(node[e].ch);
e = node[e].f;
}
for(int i = 0; i < v.size(); i++)
putchar(v[i]);
puts("");
}
int main(){
// freopen("in.txt", "r", stdin);
d[1] = 1;
for(int i = 2; i <= 9; i++)
d[i] = d[i-1] * i;
Bfs();
char g[50];
while(gets(g)){
int e = 0;
for(int i = 0; g[i]; i++){
if(g[i] != ' ')
g[e++] = g[i];
if(g[i] == 'x')
g[e-1] = '0';
}
e = cal(g);
if(vis[e])
print(vis[e]);
else
puts("unsolvable");
}
return 0;
}
2.双向广度优先搜索(hdu上904ms)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define maxn 400005
using namespace std;
struct Node{
char p[10];
char ch;
int f, x, y;
}node[maxn];
int vis[maxn];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char k[2][4] = {{'r', 'l', 'd', 'u'}, {'l', 'r', 'u', 'd'}};
int d[10], m;
queue<int> q[2];
int cal(const char *p){
int ans = 0;
for(int i = 0; i < 9; i++){
int cnt = 0;
for(int j = i+1; j < 9; j++){
if(p[i] > p[j])
cnt++;
}
ans += d[8-i] * cnt;
}
return ans;
}
void Init(){
d[1] = 1;
for(int i = 2; i < 9; i++)
d[i] = d[i-1] * i;
while(!q[0].empty())
q[0].pop();
while(!q[1].empty())
q[1].pop();
memset(vis, 0, sizeof(vis));
const char *p = "123456780";
strcpy(node[2].p, p);
node[2].x = 2, node[2].y = 2, node[2].f = -1;
vis[cal(p)] = -2;
}
bool judge(char *p){
int cnt = 0;
for(int i = 0; i < 9; i++)
for(int j = i+1; j < 9; j++){
if(p[i] != '0' && p[j] != '0' && p[i] > p[j])
cnt++;
}
if(cnt&1)return false;
return true;
}
void print1(int e){
if(node[e].f != -1){
print1(node[e].f);
putchar(node[e].ch);
}
}
void print2(int e){
while(node[e].f != -1){
putchar(node[e].ch);
e = node[e].f;
}
puts("");
}
bool BFS(queue<int> &q, char *kk, int u){
char p[10];
int t = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int x = node[t].x + dir[i][0];
int y = node[t].y + dir[i][1];
if(x >= 0 && x < 3 && y >= 0 && y < 3){
strcpy(p, node[t].p);
swap(p[node[t].x*3+node[t].y], p[x*3+y]);
int u1 = cal(p);
if(vis[u1] == 0){
++m;
node[m].x = x, node[m].y = y;
node[m].f = t, node[m].ch = kk[i];
strcpy(node[m].p, p);
vis[u1] = m * u;
q.push(m);
}
else if(vis[u1] * u < 0){
if(u == 1){
print1(t);
putchar(kk[i]);
print2(-vis[u1]);
}
else{
print1(vis[u1]);
putchar(kk[i]);
print2(t);
}
return true;
}
}
}
return false;
}
int main(){
// freopen("in.txt", "r", stdin);
char g[50];
while(gets(g)){
Init();
int v = -1;
for(int i = 0; g[i]; i++){
if(g[i] != ' ')
node[1].p[++v] = g[i];
if(g[i] == 'x'){
node[1].p[v] = '0';
node[1].x = v / 3;
node[1].y = v % 3;
}
}
if(!judge(node[1].p)){
puts("unsolvable");
continue;
}
node[1].p[v+1] = 0;
node[1].f = -1;
vis[cal(node[1].p)] = 1;
q[0].push(1);
q[1].push(2);
int sign = 0;
m = 2;
while(!q[0].empty() && !q[1].empty()){
int e = 1;
if(q[0].size() < q[1].size())
e = 0;
if(BFS(q[e], k[e], e == 0 ? 1 : -1)){
sign = 1;
break;
}
}
if(sign == 0){
puts("unsolvable");
}
}
return 0;
}
3.启发式搜索(HDU717ms)
发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n)
其中f(n) 是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#define maxn 400005
using namespace std;
typedef long long ll;
struct Node{
char p[10];
int pre;
int w, h, x, y;
char ch;
}node[maxn];
struct cmp{
bool operator ()(const int &a, const int &b){
int f1 = node[a].w + node[a].h;
int f2 = node[b].w + node[b].h;
return (f1 == f2 && node[a].h > node[b].h) || f1 > f2;
}
};
int vis[maxn], d[10], e = 46233, m;
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char kk[4] = {'r', 'l', 'd', 'u'};
int cal(const char *p){
int ans = 0;
for(int i = 0; i < 9; i++){
int k = 0;
for(int j = i + 1; j < 9; j++)
if(p[j] < p[i])
k++;
ans += d[8-i] * k;
}
return ans;
}
bool judge(char *p){
int cnt = 0;
for(int i = 0; i < 9; i++)
for(int j = i+1; j < 9; j++)
if(p[i] != '0' && p[j] != '0' && p[i] > p[j])
cnt++;
if(cnt&1)
return false;
return true;
}
int get_h(char *p){
int ans = 0;
for(int i = 0; i < 9; i++){
if(p[i] != '0')
ans += abs(i/3-(p[i]-'0'-1)/3) + abs(i%3-(p[i]-'0'-1)%3);
}
return ans;
}
void print(int v){
if(node[v].pre != -1){
print(node[v].pre);
putchar(node[v].ch);
}
}
bool Bfs(){
char p[10];
priority_queue<int, vector<int>, cmp> q;
q.push(1);
int c = cal(node[1].p);
if(c == e){
puts("");
return true;
}
vis[c] = 1;
while(!q.empty()){
c = q.top();
q.pop();
for(int i = 0; i < 4; i++){
int x = node[c].x + dir[i][0];
int y = node[c].y + dir[i][1];
if(x >= 0 && x < 3 && y >= 0 && y < 3){
strcpy(p, node[c].p);
swap(p[3*node[c].x+node[c].y], p[3*x+y]);
int v = cal(p);
if(vis[v] == 0){
vis[v] = 1;
++m;
strcpy(node[m].p, p);
node[m].w = node[c].w + 1;
node[m].h = get_h(node[m].p);
node[m].x = x, node[m].y = y;
node[m].pre = c, node[m].ch = kk[i];
q.push(m);
}
if(v == e){
print(m);
puts("");
return true;
}
}
}
}
return false;
}
int main(){
// freopen("in.txt", "r", stdin);
d[1] = 1;
for(int i = 2; i <= 9; i++)
d[i] = d[i-1] * i;
char g[50];
while(gets(g)){
memset(vis, 0, sizeof(vis));
m = 1;
int k = -1;
for(int i = 0; g[i]; i++){
if(g[i] != ' ')
node[1].p[++k] = g[i];
if(g[i] == 'x'){
node[1].p[k] = '0';
node[1].x = k / 3;
node[1].y = k % 3;
}
}
if(!judge(node[1].p)){
puts("unsolvable");
continue;
}
node[1].p[k+1] = 0;
node[1].pre = -1;
node[1].w = 0, node[1].h = get_h(node[1].p);
if(!Bfs())
puts("unsolvable");
}
return 0;
}