迷宫问题的启发式搜索解决方法

问题描述:

迷宫实验是取自心理学的一个古典实验。在该实验中,把一只老鼠从一个无顶大盒子的门放入,在盒子中设置了许多墙,对行进方向形成了多处阻挡。盒子仅有一个出口,在出口处放置一块奶酪,吸引老鼠在迷宫中寻找道路以到达出口。对同一只老鼠重复进行上述实验,一直到老鼠从入口到出口,而不走错一步。老鼠经过多次试验终于得到它学习走通迷宫的路线。设计一个计算机程序对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

题目要求:

利用一个二维数组mg[x][y]表示迷宫,其中1<=x<=n,1<=y<=m。数组元素值为1表示该位置是墙壁,不能通行;元素值为0表示该位置是通路。假定从mg[1][1]出发,出口位于mg[n][m],移动方向是( 上   下    左    右  )四个方向。用一种标志(如数字8)在二维数组中标出该条通路,并在屏幕上输出二维数组。

实现思路

(1) 首先创建三个二维数组,一个用来盛装当前迷宫的图案,另外一个用来标记这个点是否是扩展过,如果扩展过我们标记为1。

(2)创建point结构体,先x,y坐标,和估价值cost,我们使用当前坐标和目标坐标的距离作为值,并且距离越小,优先级越高。

(3)创建优先级队列,队列最顶端是优先级最高的节点,我们开始阶段将start节点放置到队列中,如果开始节点和终点节点一致,搜索成功,退出

(4)将队列中优先级最高的节点弹出,扩展此节点,如果符合条件(上,下,左,右)扩展,然后判断是否是最终节点,如果不是,将此节点放入到队列中,循环进行,直至到最终节点。

(5)然后,我加了个记录最优路径的数组,可以将每次扩展的节点进行记录,最终可输出最优路径。

代码实现

#include 
#include "stdafx.h"
#include 
#include 
#include 
#define ROWS 6
#define COLS 6
using namespace std;
//迷宫规模的大小
int rows = 6;
int cols = 6;
int matri[ROWS][COLS];//迷宫的规模
int mark[ROWS][COLS];//标记已经走过的点
int mypath[ROWS][COLS];//标记最终所走的路径
int start_x;
int start_y;
int des_x;
int des_y;
void initMap()//初始化地图
{
	for(int i=0;i p.cost;
	}
	point(int x1, int y1,int step1) 
	{
		x = x1;
		y = y1;
		step = step1;
		cost = setCost();
    }
	float setCost()
	{
		int a = x - des_x;
		int b = y - des_y;
		int c = a * a + b * b;
		return sqrt(c);
	}
};
priority_queue que; //将符合条件的点放入到这个地方
bool end(point a, point b)
{
	if (a.x == b.x) {
		if (a.y == b.y)
			return 1;
	}
	return 0;
}
int canmove(int x) {
	if (x >= 0 && x <= ROWS)
		return x;
	else return -1;
}
int findPath()
{
	//将起始点放入到这列表中
	point des(des_x, des_y, 0);
	point start(start_x, start_y, 1);
	que.push(start);//将点压入到队列中
	mark[start_x][start_y] = 1;//标记
	
	while(!que.empty())
	{
		//取出一位
		point temp = que.top();
		que.pop();
		if (end(temp, des))  return temp.step;
		mypath[temp.x][temp.y] = 1;//标记走过的路
		if ((canmove(temp.x - 1)!=-1)&&(matri[temp.x-1][temp.y]==1))      //上移
		{
			point tempN_up(temp.x - 1, temp.y, temp.step + 1);
			//cout << temp.x-1 << " " << temp.y << endl;
			if (end(tempN_up, des)) return temp.step + 1;
			if (mark[tempN_up.x][tempN_up.y] == 0)
				que.push(tempN_up);
		}
		if ((canmove(temp.x + 1)!=-1)&&(matri[temp.x+1][temp.y]==1))      //下移
		{
			point tempN_down(temp.x + 1, temp.y, temp.step + 1);
			//cout << temp.x+1 << " " << temp.y << endl;
			if (end(tempN_down, des)) return temp.step + 1;
			if (mark[tempN_down.x][tempN_down.y] == 0)
				que.push(tempN_down);
		}
		if ((canmove(temp.y - 1)!=-1)&&(matri[temp.x][temp.y-1]==1))      //左移
		{
			point tempN_left(temp.x, temp.y - 1, temp.step + 1);
			//cout << temp.x << " " << temp.y-1 << endl;
			if (end(tempN_left, des)) return temp.step + 1;
			if (mark[tempN_left.x][tempN_left.y] == 0)
				que.push(tempN_left);
		}
		if ((canmove(temp.y + 1)!=-1)&&matri[temp.x][temp.y+1]==1)      //右移
		{
			point tempN_right(temp.x, temp.y + 1, temp.step + 1);
			//cout << temp.x << " " << temp.y +1<< endl;
			if (end(tempN_right, des)) return temp.step + 1;
			if (mark[tempN_right.x][tempN_right.y] == 0)
				que.push(tempN_right);

		}
	}
	return -1;
}
void input()
{
	for(int i=0;i> matri[i][j];
		}
}
int main()
{
	printf("输入一个6*6的矩阵\n");
	input();
	printf("设定起始的x,y的值\n");
	cin >> start_x >> start_y;
	printf("设定目标的x,y的值\n");
	cin >> des_x >> des_y;
	int n = findPath();
	mypath[des_x][des_y] = 1;
	printf("一共扩展了%d次\n", n);
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
			cout << mypath[i][j] << " ";
		cout << endl;

	}
}

迷宫问题的启发式搜索解决方法_第1张图片

迷宫问题的启发式搜索解决方法_第2张图片

这种全局式的启发函数方法比较类似的还有八数码问题,有兴趣可浏览博客

 

 

 

 

 

你可能感兴趣的:(迷宫问题的启发式搜索解决方法)