hdu1043 双向bfs+康拓展开【经典】

版权声明:那个,最起码帮我加点人气吧,署个名总行吧 https://blog.csdn.net/qq_41670466/article/details/84110090

题意大致就是给你一个3X3的矩阵,你要把矩阵转换成12345678的形式,在矩阵中是有一个空缺处可以供你移动滑块的,问你是否可以把给你的矩阵转换成12345678的形式,算了题意自己去看吧,有图更加直接

思路:这里主要考虑这几个方面:第一个如何判断经过一定转换的矩阵是规范矩阵?这里就用到了康拓展开,通过康拓展开来把当前的矩阵转换为一个数值,(哈希的思想)然后去参考是否和规范矩阵的康拓展卡的哈希值一样,如果一样那么就代表成功。然后就是如何判断这个矩阵是不可以解决的矩阵:由题意可得如果两个数交换那么这个矩阵就为不可解决的矩阵,于是我们只要判断这个矩阵的逆序数就好,如果逆序数为偶数个,那么可以解决,如果为奇数,则不可解决,输出unsolvable,同时为了以防万一在bfs判定时如果也不能找到答案,也输出不可解决。

代码:

#include<string>
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn = 5e5 + 10;
int vis[maxn];
int vis2[maxn];
char d[10] = { "udlr" }, d2[10] = { "durl" };
int dir[4] = { -3,3,-1,1 };
int ha[9] = { 40320,5040,720,120,24,6,2,1,1 };
string a, b = "123456780";
struct node
{
		int num;
		char ch;
}pre[maxn];

struct node2
{
		int num;
		string s;
}e;

void show(int x)
{
		if (pre[x].num == -1)
				return;
		show(pre[x].num);
		printf("%c", pre[x].ch);
}

int getha(string s)
{
		int sum = 0;
		for (int i = 0; i < 9; i++)
		{
				int k = 0;
				for (int j = i + 1; j < 9; j++)
				{
						if (s[j] < s[i])k++;
				}
				sum+= k * ha[i];
		}
		return sum;
}

void bfs()
{
		int q = getha(e.s);
		queue<node2>q1;
		queue<node2>q2;
		vis[q] = 1;
		node2 f,g;
		f.s = b;
		f.num = 8;
		int p = getha(f.s);
		int x,k;
		vis2[p] = 2;
		pre[1].num = -1;
		pre[2].num = -1;
		int num = 2;
		q1.push(e);
		q2.push(f);
		while (!q1.empty() && !q2.empty())
		{
				f = q1.front();
				q1.pop();
				p = getha(f.s);
				if (vis2[p])
				{
						show(vis[p]);
						 k = vis2[p];
						while (pre[k].num != -1)
						{
								printf("%c", pre[k].ch);
								k = pre[k].num;
						}
						printf("\n");
						return;
				}
				for (int i = 0; i < 4; i++)
				{
						if (i == 0 && f.num < 3)		continue;
						if (i == 1 && f.num > 5)		continue;
						if (i == 2 && f.num % 3 == 0)	continue;
						if (i == 3 && f.num % 3 == 2)	continue;
						x = f.num + dir[i];
						g = f;
						swap(g.s[f.num], g.s[x]);
						q = getha(g.s);
						if (vis[q])		continue;
						vis[q] = ++num;
						g.num = x;
						pre[num].num = vis[p];
						pre[num].ch = d[i];
						q1.push(g);
				}
				f = q2.front();
				q2.pop();
				p = getha(f.s);
				if (vis[p])
				{
						show(vis[p]);
						k = vis2[p];
						while (pre[k].num != -1)
						{
								printf("%c", pre[k].ch);
								k = pre[k].num;
						}
						printf("\n");
						return;
				}
				for (int i = 0; i < 4; i++)
				{
						if (i == 0 && f.num < 3)		continue;
						if (i == 1 && f.num > 5)		continue;
						if (i == 2 && f.num % 3 == 0)	continue;
						if (i == 3 && f.num % 3 == 2)	continue;
						x = f.num + dir[i];
						g = f;
						swap(g.s[f.num], g.s[x]);
						q = getha(g.s);
						if (vis2[q])		continue;
						vis2[q] = ++num;
						g.num = x;
						pre[num].num = vis2[p];
						pre[num].ch = d2[i];
						q2.push(g);
				}
		}
		printf("unsolvable\n");
}

int main()
{
		while (getline(cin, a))
		{
				int n, k = 0;
				n = a.size();
				e.s = "";
				for (int i = 0, j = 0; i < n; i++)
				{
						if (a[i] != ' ')
						{
								if (a[i] == 'x')
								{
										e.num = j;
										e .s+= '0';
								}
								else
										e.s += a[i];
								j++;
						}
				}
				for (int i = 0; i < 9; i++)
				{
						if (e.s[i] == '0')	continue;
						for (int j = 0; j < i; j++)
						{
								if (e.s[j] == '0')	continue;
								if (e.s[j] > e.s[i])		k++;
						}
				}
				memset(vis2, 0, sizeof(vis2));
				memset(vis, 0, sizeof(vis));
				if (k & 1) printf("unsolvable\n");
				else
						bfs();
		}
		system("pause");
		return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41670466/article/details/84110090