AStar算法求解迷宫最短路径问题

 我这个仅针对7行7列的迷宫写的,写的比较急,要计算n行m列的迷宫稍微改下就行了

代码如下,若有不妥请高手指点:

#include <iostream>
#include <set>
#include <string>
#include <cmath>
#include <cstdlib>
#define N 100

using namespace std;

struct node
{
	double h,g,f;
	int x,y;	
	bool operator<(node other)const
	{
		return f<other.f;
	}
};
int map[N][N];//迷宫,1表示可以走,0表示不可以走
int row,col;//矩阵的行和列
multiset<node> open;//可以拓展节点
multiset<node>::iterator it;
node close[N][N];//已经走过的节点
int step[8][2] = {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1};//走的方式
int prev[N*N];//存放前一个节点
void Init()
{
	memset(close,0,sizeof(close));
}

double getg(node a,node b)//获取当前点到终点的路径值
{
	return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));	
}
bool Is_Match(node a,node b)
{
	if(a.x == b.x && a.y == b.y)
	{
		return true;	
	}	
	return false;
}
node begin,end;
int main()
{
	while(cin>>row>>col)
	{
		open.clear();
		Init();
		for(int i=0;i<row;i++)//输入迷宫
		{
			for(int j=0;j<col;j++)
			{
				cin>>map[i][j];	
			}	
		}	
		cin>>begin.x>>begin.y>>end.x>>end.y;//起始点和终点		
		begin.g = getg(begin,end);//初始化起始点的估值函数
		begin.f = begin.g;
		begin.h = 0;
		open.insert(begin);//open表插入起点
		bool IsSuccess = false;
		while(!open.empty())//但还有节点可以走
		{
			node son = *(open.begin());//取出路径消耗+估值函数最小的节点
			open.erase(open.begin());//从open表中删除上面的节点
			for(int i=0;i<8;i++)//探寻8个方向
			{
				int u = son.x+step[i][0];
				int v = son.y+step[i][1];
				if(u>=0&&v>=0&&u<row&&v<col&&map[u][v])//如果这个节点在矩阵中,且值为1,可以走
				{
					//更新这个节点的信息,包括路径消耗和估值函数
					node tmp;
					tmp.x = u;
					tmp.y = v;
					tmp.g = getg(tmp,end);
					tmp.h = son.h+1;
					tmp.f = tmp.h + tmp.g;
					bool IsInOpen = false;//表示是否在open表中
					if(u == end.x&&v == end.y)//如果是终点,就退出循环
					{
						prev[u*7+v] = son.x*7+son.y;//记录前一个节点
						IsSuccess = true;//表示成功找到了路径
						goto BreakPoint;	
					}
					for(it = open.begin();it!=open.end();it++)
					{
						//如果在open表中,比较tmp这个点与open表中的f的大小,如果前者f小就把tmp插入到open表中
						if(Is_Match(*it,tmp))
						{
							IsInOpen = true;//表示在open表中
							if((*it).f>tmp.f)
							{
								node New = tmp;
								open.erase(it);			
								open.insert(tmp);
								prev[tmp.x*7+tmp.y] = son.x*7+son.y;//记录前一个节点
								break;	
							}	
						}	
					}
					bool IsInClose = false;//标记是否在close表中
					if(close[tmp.x][tmp.y].f)//如果在close中,表示已经走过,再次比较f的大小,如果前者f小,把这个点插入到open表中,并从close表中删除这个点。
					{
						IsInClose = true;//在close表中
						if(tmp.f < close[tmp.x][tmp.y].f)
						{
							open.insert(tmp);
							close[tmp.x][tmp.y].f = 0;	
							close[tmp.x][tmp.y].g = 0;
							close[tmp.x][tmp.y].h = 0;
								
							prev[tmp.x*7+tmp.y] = son.x*7+son.y;//记录前一个节点
						}	
					}
					if(!IsInOpen&&!IsInClose)//如果既不在close表中,也不在open表中,表示没有走过,把这个节点插入open表中。
					{
						open.insert(tmp);	
						prev[tmp.x*7+tmp.y] = son.x*7+son.y;//记录前一个节点
					}
				}	
				
			}
			//把从open表中取出点得放到close表中,表示已经走过
			close[son.x][son.y].x = son.x;
			close[son.x][son.y].y = son.y;
			close[son.x][son.y].g = son.g;
			close[son.x][son.y].f = son.f;
			close[son.x][son.y].h = son.h;	
		}
BreakPoint:;
		if(IsSuccess)//如果成功找到了路径,输出路径,我没有去反序输出结果,所以点是倒着的。
		{
			cout<<"The Path Is:"<<endl;
			int x = end.x*7+end.y;
			int y = begin.x*7+begin.y;
			while(x!=y)
			{
				cout<<"("<<x/7<<","<<x%7<<") -- > ";
				x = prev[x];
			}
			cout<<"("<<begin.x<<","<<begin.y<<")"<<endl;
			cout<<endl;
			cout<<"Reach Success!"<<endl;
		}
		else //不能到达终点
		{
			cout<<"Reach Failed!"<<endl;
		}
	}	
}


 

  • 2
    点赞
  • 3
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

sjjwind

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值