HDU3567 进阶搜索 IDA*算法 八数码【经典】

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

题意是给你两个八数码,让你输出从第一个八数码到第二个八数码的最短路径,且要求该路径也是最短路径下的字典序最小的路径。

思路:我一开始以为只是简单的在结构体判定一下,让其按照字典序最小的顺序去寻路,后来发现这样做的后果是路径不是最小,嗯。于是就上网查博客,然后就学会了A*算法的升级版IDA A*算法,在这里简单的说一下也加深一下自己的印象:ida算法是A*算法的进化版,它舍弃了a*算法的空间消耗,没有维护判定点和未判定点的数组,而是先按照一个限定值,在这个限定值下去查找,如果在这个限定值下找到解,那么这个解一定是最优解,如果找不到,那么扩大限定值,重复,这样就对空间进行了优化,同时通过迭代加深搜索的剪枝,在某些题,时间出奇的好。

更加详细的请:https://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756

代码:

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

using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
int m[20];
int posgoal[20];//用来储存第二个八数码表里每个数字的位置。
int dir[4][2] = { {1,0},{0,-1},{0,1},{-1,0} };
int fac[9] = { 1,1,2,6,24,120,720,5040,40320 };
char op[4] = { 'd','l','r','u' };//这也是本题之所以是输出字典序最小解的原因,因为是dfs的主题框架啊,所以我可以让它按照字典序的最小的方式去搜,如果有答案,那么一定符合字典序最小解。

int hash(int s[])//八数码问题常用的利用康托展开来进行hash表的建立
{
		int sum = 0;
		for (int i = 0; i < 9; i++)
		{
				int k = 0;
				for (int j = i + 1; j < 9; j++)
						if (s[i] > s[j])   k++;
				sum += k * fac[8 - i];
		}
		return sum+1;
}

int geth(int s[])//这里用曼哈顿距离来预估距离(每个数字恢复到第二个八数码的曼哈顿距离的和)
{
		int dis = 0;
		for (int i = 0; i < 9; i++)
		{
				if (s[i] != 9)
				{
						int x = i / 3, y = i % 3;
						int xx = posgoal[s[i]]/3, yy = posgoal[s[i] ]%3;
						dis += abs(x - xx) + abs(y - yy);
				}
		}
		return dis;
}

char path[100];
int cas, nextd;
bool idaal(int loc, int depth, int pre, int limit)
{
		int h = geth(m);
		if (depth + h > limit)
		{
				nextd = min(nextd, depth + h);
				return false;
		}
		if (h == 0)
		{
				path[depth] = '\0';
				printf("Case %d: %d\n", cas, depth);
				puts(path);
				return true;
		}
		int x = loc / 3, y = loc % 3;
		for (int i = 0; i < 4; i++)
		{
				if (pre + i == 3)    continue;
				int xx = x + dir[i][0];
				int yy = y + dir[i][1];
				if (xx < 0 || xx >= 3 || yy < 0 || yy >= 3)    continue;
				int temloc = xx * 3 + yy;
				swap(m[loc], m[temloc]);
				path[depth] = op[i];
				if (idaal(temloc, depth + 1, i, limit))   return true;
				swap(m[loc], m[temloc]);
		}
		return false;
}

int main()
{
		int t;
		scanf("%d", &t);
		char str[50];
		for (cas = 1; cas <= t; cas++)
		{
				int loc;
				scanf("%s", str);
				for (int i = 0; i < 9; i++)
				{
						if (str[i] == 'X') m[i] = 9, loc = i;
						else m[i] = str[i] - '0';
				}
				scanf("%s", str);
				for (int i = 0; i < 9; i++)
				{
						if (str[i] == 'X') posgoal[9] = i;
						else posgoal[str[i] - '0'] = i;
				}
				for (int limit = geth(m);; limit = nextd)
				{
						nextd = inf;
						if (idaal(loc, 0, inf, limit))//如果返回的是false,则扩大limit的值
								break;
				}
		}
		//system("pause");
		return 0;
}

猜你喜欢

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