天天看點

HDU 1043 Eight

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;
}