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 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. Do not print a blank line between cases.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
先膜拜下這位大神http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html
總結了此題的八境界。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 4;
const int cnt = 3;
int a[cnt][cnt], c[maxn << 2], f[500000], x, y, z;
int b[maxn] = { -1, 1, 0, 0 };
int d[maxn] = { 0, 0, 1, -1 };
char e[maxn + 1] = { "udrl" };
class abc
{
public:
int a[cnt][cnt], x, y, z;
string s;
abc(){};
abc(int a[cnt][cnt], int x, int y, int z, string s)
{
this->s = s;
this->x = x;
this->y = y;
this->z = z;
memcpy(this->a, a, sizeof(this->a));
}
};
bool insert()
{
char s[2];
for (int i = 0; i < 3;i++)
for (int j = 0; j < 3;j++)
if (scanf("%s", s) == EOF) return false;
else
{
a[i][j] = min(9, s[0] - '0');
if (a[i][j] == 9) x = i, y = j;
}
return true;
}
int get(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 9; i++)
{
int k = 0;
for (int j = 0; j < i; j++)
if (a[j / 3][j % 3]>a[i / 3][i % 3]) k++;
tot += k * c[i];
}
return tot;
}
void bfs(int a[cnt][cnt])
{
memset(f, 0, sizeof(f));
queue<abc> p;
z = get(a);
p.push(abc(a, x, y, z, ""));
f[z] = 1;
while (!p.empty())
{
abc q = p.front(); p.pop();
if (q.z == 0) { cout << q.s << endl; return; }
for (int i = 0; i < maxn; i++)
{
x = q.x + b[i]; y = q.y + d[i];
if (x>=0 && x<cnt && y>=0 && y < cnt)
{
swap(q.a[q.x][q.y], q.a[x][y]);
z = get(q.a);
if (!f[z]){ f[z] = 1; p.push(abc(q.a, x, y, z, q.s + e[i])); }
swap(q.a[q.x][q.y], q.a[x][y]);
}
}
}
printf("unsolvable\n");
}
int main()
{
for (int i = c[0] = 1; i < 9; i++) c[i] = c[i - 1] * i;
while (insert()) bfs(a); return 0;
}
從終點開始搜回去然後hash判重,打表輸出。hdu 500ms ac
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 4;
const int cnt = 3;
int a[cnt][cnt], c[maxn << 2], x, y, z;
int b[maxn] = { 0, -1, 0, 1 };
int d[maxn] = { 1, 0, -1, 0 };
char e[maxn + 1] = { "ldru" };
string f[500000];
class abc
{
public:
int a[cnt][cnt], x, y, z;
abc(){};
abc(int a[cnt][cnt], int x, int y, int z)
{
this->x = x;
this->y = y;
this->z = z;
memcpy(this->a, a, sizeof(this->a));
}
};
bool insert()
{
char s[2];
for (int i = 0; i < 3;i++)
for (int j = 0; j < 3;j++)
if (scanf("%s", s) == EOF) return false;
else a[i][j] = min(9, s[0] - '0');
return true;
}
int get(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 9; i++)
{
int k = 0;
for (int j = 0; j < i; j++)
if (a[j / 3][j % 3]>a[i / 3][i % 3]) k++;
tot += k * c[i];
}
return tot;
}
void bfs(int a[cnt][cnt])
{
memset(f, 0, sizeof(f));
queue<abc> p;
z = get(a);
p.push(abc(a, 2, 2, z));
f[z] = "";
while (!p.empty())
{
abc q = p.front(); p.pop();
for (int i = 0; i < maxn; i++)
{
x = q.x + b[i]; y = q.y + d[i];
if (x>=0 && x<cnt && y>=0 && y < cnt)
{
swap(q.a[q.x][q.y], q.a[x][y]);
z = get(q.a);
if (!f[z][0]){
f[z] = e[i] + f[q.z];
p.push(abc(q.a, x, y, z));
}
swap(q.a[q.x][q.y], q.a[x][y]);
}
}
}
}
int main()
{
for (int i = c[0] = 1; i < 9; i++)
{
c[i] = c[i - 1] * i;
a[(i - 1) / 3][(i - 1) % 3] = i;
a[2][2] = 9;
}
bfs(a);
while (insert()) if (f[get(a)][0]) cout << f[get(a)] << endl; else printf("unsolvable\n");
return 0;
}
雙廣,hdu 爆記憶體
poj 125ms
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 4;
const int cnt = 3;
int a[cnt][cnt], c[maxn << 2], x, y, z;
int b[maxn] = { -1, 0, 1, 0 };
int d[maxn] = { 0, -1, 0, 1 };
int zz[2];
char e[2][maxn + 1] = { "uldr", "drul" };
string f[2][400000];
class abc
{
public:
int a[cnt][cnt], x, y, z, id;
abc(){};
abc(int a[cnt][cnt], int x, int y, int z, int id)
{
this->id = id;
this->x = x;
this->y = y;
this->z = z;
memcpy(this->a, a, sizeof(this->a));
}
};
bool insert()
{
char s[2];
for (int i = 0; i < 3;i++)
for (int j = 0; j < 3;j++)
if (scanf("%s", s) == EOF) return false;
else
{
a[i][j] = min(9, s[0] - '0');
if (a[i][j] == 9) x = i, y = j;
}
return true;
}
int get(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 9; i++)
{
int k = 0;
for (int j = 0; j < i; j++)
if (a[j / 3][j % 3]>a[i / 3][i % 3]) k++;
tot += k * c[i];
}
return tot;
}
void bfs(int a[cnt][cnt])
{
memset(f, 0, sizeof(f));
queue<abc> p;
zz[0] = get(a);
p.push(abc(a, x, y, zz[0], 0));
f[0][zz[0]] = "";
for (int i = 0; i < 9; i++) a[i / 3][i % 3] = i + 1;
zz[1] = get(a);
p.push(abc(a, 2, 2, zz[1], 1));
f[1][zz[1]] = "";
while (!p.empty())
{
abc q = p.front(); p.pop();
for (int i = 0; i < maxn; i++)
{
x = q.x + b[i]; y = q.y + d[i];
if (x>=0 && x<cnt && y>=0 && y < cnt)
{
swap(q.a[q.x][q.y], q.a[x][y]);
z = get(q.a);
if (!f[q.id][z][0]){
if (q.id) f[q.id][z] = e[q.id][i] + f[q.id][q.z];
else f[q.id][z] = f[q.id][q.z] + e[q.id][i];
if (f[1 - q.id][z][0] || z == zz[1 - q.id])
{
cout << f[0][z] << f[1][z] << endl;
return;
} else p.push(abc(q.a, x, y, z, q.id));
}
swap(q.a[q.x][q.y], q.a[x][y]);
}
}
}
printf("unsolvable\n");
}
int main()
{
for (int i = c[0] = 1; i < 9; i++) c[i] = c[i - 1] * i;
while (insert()) bfs(a); return 0;
}
A*+哈希+簡單估價函數+優先隊列poj 63ms
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 4;
const int cnt = 3;
int a[cnt][cnt], c[maxn << 2], x, y, z, g, h;
int b[maxn] = { -1, 0, 1, 0 };
int d[maxn] = { 0, -1, 0, 1 };
char e[maxn + 1] = { "uldr" };
int ins[400000][2];
string f[400000];
struct abc
{
int a[cnt][cnt], x, y, z;
abc(){};
abc(int a[cnt][cnt], int x, int y, int z)
{
this->x = x;
this->y = y;
this->z = z;
memcpy(this->a, a, sizeof(this->a));
}
};
struct cmp{
bool operator()(const abc&a, const abc&b)
{
return ins[a.z][1] + ins[a.z][2] > ins[b.z][1] + ins[b.z][2];
}
};
bool insert()
{
char s[2];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (scanf("%s", s) == EOF) return false;
else
{
a[i][j] = min(9, s[0] - '0');
if (a[i][j] == 9) x = i, y = j;
}
return true;
}
int get(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 9; i++)
{
int k = 0;
for (int j = 0; j < i; j++)
if (a[j / 3][j % 3]>a[i / 3][i % 3]) k++;
tot += k * c[i];
}
return tot;
}
int find(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 8; i++)
if (a[i / 3][i % 3] != i + 1) tot++;
return tot;
}
void bfs(int a[cnt][cnt])
{
memset(f, 0, sizeof(f));
memset(ins, 0, sizeof(ins));
priority_queue<abc, vector<abc>, cmp> p;
z = get(a); f[z] = "";
p.push(abc(a, x, y, z));
ins[z][0] = 0; ins[z][1] = find(a);
while (!p.empty())
{
abc q = p.top(); p.pop();
if (!q.z){ cout << f[q.z] << endl; return; }
for (int i = 0; i < maxn; i++)
{
x = q.x + b[i]; y = q.y + d[i];
if (x >= 0 && x<cnt && y >= 0 && y < cnt)
{
swap(q.a[q.x][q.y], q.a[x][y]);
z = get(q.a);
g = ins[q.z][0] + 1;
h = find(q.a);
if ((!(ins[z][0] + ins[z][1]))|| ins[z][0] + ins[z][1]>h + g)
{
f[z] = f[q.z] + e[i];
ins[z][0] = g; ins[z][1] = h;
p.push(abc(q.a, x, y, z));
}
swap(q.a[q.x][q.y], q.a[x][y]);
}
}
}
printf("unsolvable\n");
}
int main()
{
for (int i = c[0] = 1; i < 9; i++) c[i] = c[i - 1] * i;
while (insert()) bfs(a); return 0;
}
A*+哈希+曼哈頓距離+優先隊列 poj 47ms
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 4;
const int cnt = 3;
int a[cnt][cnt], c[maxn << 2], x, y, z, g, h;
int b[maxn] = { -1, 0, 1, 0 };
int d[maxn] = { 0, -1, 0, 1 };
char e[maxn + 1] = { "uldr" };
int ins[400000][2];
string f[400000];
struct abc
{
int a[cnt][cnt], x, y, z;
abc(){};
abc(int a[cnt][cnt], int x, int y, int z)
{
this->x = x;
this->y = y;
this->z = z;
memcpy(this->a, a, sizeof(this->a));
}
};
struct cmp{
bool operator()(const abc&a, const abc&b)
{
return ins[a.z][1] + ins[a.z][2] > ins[b.z][1] + ins[b.z][2];
}
};
bool insert()
{
char s[2];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (scanf("%s", s) == EOF) return false;
else
{
a[i][j] = min(9, s[0] - '0');
if (a[i][j] == 9) x = i, y = j;
}
return true;
}
int get(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < 9; i++)
{
int k = 0;
for (int j = 0; j < i; j++)
if (a[j / 3][j % 3]>a[i / 3][i % 3]) k++;
tot += k * c[i];
}
return tot;
}
int find(int a[cnt][cnt])
{
int tot = 0;
for (int i = 0; i < cnt; i++)
for (int j = 0; j < cnt; j++)
{
int x = (a[i][j] - 1) / 3;
int y = (a[i][j] - 1) % 3;
tot += abs(x - i) + abs(y - j);
}
return tot;
}
void bfs(int a[cnt][cnt])
{
memset(f, 0, sizeof(f));
memset(ins, 0, sizeof(ins));
priority_queue<abc, vector<abc>, cmp> p;
z = get(a); f[z] = "";
p.push(abc(a, x, y, z));
ins[z][0] = 0; ins[z][1] = find(a);
while (!p.empty())
{
abc q = p.top(); p.pop();
if (!q.z){ cout << f[q.z] << endl; return; }
for (int i = 0; i < maxn; i++)
{
x = q.x + b[i]; y = q.y + d[i];
if (x >= 0 && x<cnt && y >= 0 && y < cnt)
{
swap(q.a[q.x][q.y], q.a[x][y]);
z = get(q.a);
g = ins[q.z][0] + 1;
h = find(q.a);
if ((!(ins[z][0] + ins[z][1])) || ins[z][0] + ins[z][1]>h + g)
{
f[z] = f[q.z] + e[i];
ins[z][0] = g; ins[z][1] = h;
p.push(abc(q.a, x, y, z));
}
swap(q.a[q.x][q.y], q.a[x][y]);
}
}
}
printf("unsolvable\n");
}
int main()
{
for (int i = c[0] = 1; i < 9; i++) c[i] = c[i - 1] * i;
while (insert()) bfs(a); return 0;
}
IDA*+曼哈頓距離 hdu 187ms
poj 16ms
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<functional>
#include<string>
using namespace std;
const int maxn = 3;
const int maxd = 100;
int a[maxn][maxn], x, y, f;
int b[2][maxn + 1] = { 0, -1, 0, 1, 1, 0, -1, 0 };
char d[maxn + 2] = { "ruld" };
char ans[maxd];
map<char, char> M;
bool insert()
{
char s[2];
for (int i = 0; i < maxn; i++)
for (int j = 0; j < maxn; j++)
if (scanf("%s", s) == EOF) return false;
else
{
a[i][j] = min(9, s[0] - '0');
if (a[i][j] == 9) x = i, y = j;
}
return true;
}
bool check(int a[maxn][maxn])
{
for (int i = 0; i < maxn; i++)
for (int j = 0; j < maxn; j++)
if (a[i][j] != i + i + i + j + 1) return false;
return true;
}
int get()
{
int tot = 0;
for (int i = 0; i < maxn; i++)
for (int j = 0; j < maxn; j++)
{
if (a[i][j] < 9)
tot += abs((a[i][j] - 1) / 3 - i) + abs((a[i][j] - 1) % 3 - j);
}
return tot;
}
void dfs(int h, int ax, int ay, int deep, int max_d)
{
if (deep + h >= max_d || f) return;
if (check(a))
{
ans[deep] = '\0';
f = 1; return;
}
int bx, by, H = 0, g;
for (int i = 0; i <= maxn; i++)
{
if (deep&&M[d[i]] == ans[deep - 1]) continue;
bx = ax + b[0][i];
by = ay + b[1][i];
if (0 <= bx&&bx < maxn && 0 <= by&&by < maxn)
{
ans[deep] = d[i];
g = a[bx][by] - 1;
H = h - abs(g / 3 - bx) - abs(g % 3 - by);
H = H + abs(g / 3 - ax) + abs(g % 3 - ay);
swap(a[ax][ay], a[bx][by]);
dfs(H, bx, by, deep + 1, max_d);
if (f) return;
swap(a[ax][ay], a[bx][by]);
}
}
}
int cansolve()
{
int tot = 0;
for (int i = 0; i < 9; i++)
for (int j = 0; j < i; j++)
if (a[i / 3][i % 3] != 9 && a[j / 3][j % 3] != 9)
if (a[i / 3][i % 3] < a[j / 3][j % 3]) tot++;
return 1 - tot % 2;
}
int main()
{
M['r'] = 'l';
M['l'] = 'r';
M['d'] = 'u';
M['u'] = 'd';
while (insert())
{
f = 0;
if (!cansolve()) { printf("unsolvable\n"); continue; }
for (int i = 1; !f; i++) dfs(get(), x, y, 0, i);
if (f) printf("%s\n", ans);
}
return 0;
}