hdu 1043 eight (bfs暴力打表+康托展开)

思路:

1.首先要知道什么是康托展开,不会的自行百度吧,其实我个人感觉就是一种映射关系,将一种排列方式映射成一个数

2.bfs打表得到到达每个点的路径,然后一直找点的父节点就行;

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define esp 1e-4
using namespace std;
/*经典8数码问题,从最终情况开始到各种的情况的情况进行打表,用康托展开记录情况*/
int fac[10];//0-9的阶乘 
char final[11] = "0123456789";
int dir[4][2] = { {-1,0},{1,0},{0,-1},{0,1} };//向上,向下,向左,向右 
struct node1
{
	int f;//父节点
	char way;//到达这个点的方式 
};
struct node2
{
	char a[12];//记录状态
	int ktval;//康托值 
	int n;//代表x(9)的位置 
};
node1 path[400000];//记录每种情况 
void setfac()
{
	fac[0] = 1;
	for (int i = 1; i <= 9; i++)
		fac[i] = fac[i - 1] * i;
}
int kt(char *a)
{
	int ans = 0;
	for (int i = 1; i <= 9; i++)
	{
		int k = 0;
		for (int j = i + 1; j <= 9; j++)
		{
			if (a[i] > a[j])
			{
				k++;
			}
		}
		ans += k * fac[9 - i];
	}
	return ans;
}
void bfs()
{
	queue q;
	node2 temp;
	strcpy(temp.a, final);
	temp.ktval =0;
	temp.n = 9;//一开始9在最右下角
	path[temp.ktval].f = 0;//最终状态没有父节点 
	q.push(temp);
	while (!q.empty())
	{
		for (int i = 0; i < 4; i++)//4种走法
		{

			int nn;//下个点的位置 
			int nx, ny;//当前点的位置
			nx = (q.front().n - 1) / 3 + 1+dir[i][0];//行 
			ny = (q.front().n - 1) % 3 + 1+dir[i][1];//列
			nn = (nx - 1) * 3 + ny;
			if (nx < 1 || nx>3 || ny < 1 || ny>3)
				continue;
			char temp2[12];
			strcpy(temp2, q.front().a);
			swap(temp2[q.front().n], temp2[nn]);//换位置 
			int ktval = kt(temp2);
			if (path[ktval].f == -1)//没访问过 
			{
				strcpy(temp.a, temp2);
				temp.ktval = ktval;
				temp.n = nn;
				q.push(temp);
				path[ktval].f = q.front().ktval;
				if (i == 0) path[ktval].way = 'd';
				if (i == 1) path[ktval].way = 'u';
				if (i == 2) path[ktval].way = 'r';
				if (i == 3) path[ktval].way = 'l';
			}
		}
		q.pop();


	}

}


int main()
{
	setfac();
	for (int i = 0; i < 400000; i++)
		path[i].f = -1;//代表没访问过 
	bfs();//打表 
	string temp2;
	char temp[12];
	while (getline(cin,temp2))
	{
		int x = 1;
		for (int i = 0; i <= temp2.length(); i++)
		{
			if (temp2[i] == 'x')
			{
				temp[x++] = '9';
			}
			if (temp2[i] <= '9' && temp2[i] >= '1')
			{
				temp[x++] = temp2[i];
			}
		}
		temp[0] = '0';
		int ktval = kt(temp);
		if (path[ktval].f == -1)
		{
			cout << "unsolvable\n";
			continue;
		}
		while (ktval)
		{
			cout << path[ktval].way;
			ktval = path[ktval].f;
		}
		cout << endl;
	}



	return 0;
}

 

你可能感兴趣的:(hdu 1043 eight (bfs暴力打表+康托展开))