Problem Description
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:
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
1 2 3
x 4 6
7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
Sample Input
Sample Output
ullddrurdllurdruldr
先膜拜下这位大神http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html
总结了此题的八境界。
用string直接保存路径的暴力广搜+hash,结果自然是tle。
#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;
}
#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;
}