算法_八数码问题启发式搜索(C++)

#include<iostream>
#include<vector>
#include<string>
#include<queue>
using namespace std;
int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };//康拖展开判重//         0!1!2!3! 4! 5!  6!  7!   8!    9!
int moves[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };//u,d,l,r
char moveIndex[5] = "udlr";//正向搜索
int index[1000000] = {false};
typedef struct point
{
	int s[9];//为什么不选择二维数组呢?1、数组规模已知,一维可以转化为二维 2、二维遍历比较麻烦
	int number;//康托展开hash值 原因:1、映射到一个数字,方便比较  2、方便标记是否被访问过
	int loc;//0的位置
	int hx;
	int step;
	string path;
	void gethx(point aim)
	{
		hx = 0;
		for (int i = 0; i < 9; i++)
		{
			int x = i / 3, y = i % 3;
			for (int j = 0; j < 9; j++)
			{
				if (s[i] == aim.s[j]) 
				{
					int aimx = j / 3, aimy = j % 3;
					hx = abs(aimx - x) + abs(aimy - y);
				}
			}
		}
	}
	void sToNumber()//结构体内已经定义的变量可直接引用。那么这结构体和类的区别有哪些。构造函数???
	{
		number = 0;//在初始化是叠加了当然会导致错误智障!
		for (int i = 0; i < 9; i++)
		{
			int count = 0;
			for (int j = i + 1; j < 9; j++) if (s[j] < s[i]) count++;
			number += (fac[9 - i - 1] * count);
		}
	}
};
struct cmp{//重载括号
	bool operator()(point a, point b)
	{
		return (a.hx+a.step)>(b.hx+b.step);
	}
};
bool dfs(point &in, point &aim,string &path)
{    
	priority_queue<point,vector<point>,cmp> p;//找最小,两种方式:1、最小堆 2、优先队列 //不能不写中间那项,默认参数的规则
	in.gethx(aim);
	p.push(in);
	index[in.number] = true;
	while (!p.empty()){
		cout << 1;
		point cur = p.top();
		p.pop();
		if (cur.number==aim.number){
			path = cur.path;
			return true;
		}
		//没找到,准备交换入栈
		int x = cur.loc / 3, y = cur.loc % 3;
		//cout << x << " " << y << endl;
		for (int i = 0; i < 4; i++){
			int xtemp=x+(moves[i][0]); int ytemp=y+(moves[i][1]);//0的新位置
			if (x<0 || x>2 || y<0 || y>2) continue;
			point next(cur);
			next.loc = xtemp * 3 + ytemp;
			//cout << next.loc;
			swap(next.s[next.loc], next.s[cur.loc]);
			//for (int i = 0; i < 9; i++) cout << next.s[i] << " ";
			next.sToNumber();
			if (index[next.number] == true) continue;
			next.step++;
			next.path = cur.path + moveIndex[i];
			next.gethx(aim);
			index[next.number] = true;
			if (next.number == aim.number)
			{
				cout << "最少步数为:" << next.step << endl;
				path = next.path;
				return true;
			}
			//cout << next.number << " " << aim.number << endl;
			p.push(next);
		}
		//system("pause");
	}
	return false;
}
int main()
{
	point in, aim;
	//cout << "请输入起始位置";
	int temp1[9] = { 2,3,4,1,5,0,7,6,8 };
	int temp2[9] = { 1,2,3,4,5,6,7,8,0 };
	for (int i = 0; i < 9; i++){
		in.s[i] = temp1[i];
		if (in.s[i] == 0) in.loc = i;
	}
	in.step = 0;
	in.sToNumber();
	for (int i = 0; i < 9; i++)
	{
		aim.s[i]=temp2[i];
	}
	aim.sToNumber();
	string path;
	if (dfs(in, aim, path)){
		cout << path;	
	}
	else cout << "失败了";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38034312/article/details/80527180