# POJ-1077 HDU-1043 Eight(单广,双广,启发式搜索)

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.广搜，打表

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define maxn 400005
using namespace std;

struct Node{
char p;
int x, y, f;
char ch;
}node[maxn];
int vis[maxn], d;
int dir = {1, 0, -1, 0, 0, 1, 0, -1};
int k = {'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 = "123456780";
vis[cal(t)] = 1;
strcpy(node.p, t);
node.x = 2, node.y = 2;
node.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];
int y = node[h].y + dir[i];
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;
for(int i = 2; i <= 9; i++)
d[i] = d[i-1] * i;
Bfs();
char g;
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;
char ch;
int f, x, y;
}node[maxn];
int vis[maxn];
int dir = {0, 1, 0, -1, 1, 0, -1, 0};
char k = {{'r', 'l', 'd', 'u'}, {'l', 'r', 'u', 'd'}};
int d, m;
queue<int> q;
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;
for(int i = 2; i < 9; i++)
d[i] = d[i-1] * i;
while(!q.empty())
q.pop();
while(!q.empty())
q.pop();
memset(vis, 0, sizeof(vis));
const char *p = "123456780";
strcpy(node.p, p);
node.x = 2, node.y = 2, node.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;
int t = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int x = node[t].x + dir[i];
int y = node[t].y + dir[i];
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;
while(gets(g)){
Init();
int v = -1;
for(int i = 0; g[i]; i++){
if(g[i] != ' ')
node.p[++v] = g[i];
if(g[i] == 'x'){
node.p[v] = '0';
node.x = v / 3;
node.y = v % 3;
}
}
if(!judge(node.p)){
puts("unsolvable");
continue;
}
node.p[v+1] = 0;
node.f = -1;
vis[cal(node.p)] = 1;
q.push(1);
q.push(2);
int sign = 0;
m = 2;
while(!q.empty() && !q.empty()){
int e = 1;
if(q.size() < q.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)

#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;
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, e = 46233, m;
int dir = {0, 1, 0, -1, 1, 0, -1, 0};
char kk = {'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;
priority_queue<int, vector<int>, cmp> q;
q.push(1);
int c = cal(node.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];
int y = node[c].y + dir[i];
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;
for(int i = 2; i <= 9; i++)
d[i] = d[i-1] * i;
char g;
while(gets(g)){
memset(vis, 0, sizeof(vis));
m = 1;
int k = -1;
for(int i = 0; g[i]; i++){
if(g[i] != ' ')
node.p[++k] = g[i];
if(g[i] == 'x'){
node.p[k] = '0';
node.x = k / 3;
node.y = k % 3;
}
}
if(!judge(node.p)){
puts("unsolvable");
continue;
}
node.p[k+1] = 0;
node.pre = -1;
node.w = 0, node.h = get_h(node.p);
if(!Bfs())
puts("unsolvable");
}
return 0;
}


05-23 3326 01-16 298
05-22 296
02-13 5745
01-03 2648
09-17 789
08-21 762
08-30 389
04-25 261
11-06 479