A*搜索算法

摘要:
A*搜寻算法俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。这种算法的所获得的路径并不一定是最短路径但一定是我们所关注的某一方面价值最“优”的路径。那么如何获得的这个节点列表才算是“最优”呢?我的理解是H的作用是起到指引作用,指导下次搜索的方向尽可能向目标靠近。

A*搜寻算法俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上。

这种算法的所获得的路径并不一定是最短路径但一定是我们所关注的某一方面价值最“优”的路径。我们将地图划分为一个个节点,从出发点到目标的路径就可以使用一个节点列表来表示。那么如何获得的这个节点列表才算是“最优”呢?这就要用到我们前面提到的启发式函数,具体表示启发式函数如下:
F(p) = G(p) + H(p)
其中F值表示对象从起点经过当前节点p到达目标节点预计总消耗值,G值表示对象从起点到达当前节点p时需要消耗值,H值则表示对象从当前节点p预计到达目标节点需要消耗值。这里需要说明的是,H值是一个估价值,是对象从p点到目标点时,对我们关心的属性定义按照既定计算方式的一种消耗估计,不考虑障碍,可以用棋盘格距离度量,所以这个值并不一定准确,只是起到一个预期的评价。我的理解是H的作用是起到指引作用,指导下次搜索的方向尽可能向目标靠近。当我们对H值得估算给出不同的计算方案时,经过A星得到的路径优势点也就不同,可能是最短路径,也可能是最节省资金的路径……总之就是我们关心的这一属性上消耗最小的一条路径。

#include "stdafx.h"
#include<vector>
#include<set>
#include<algorithm>
#include<iostream>

using namespace std;
#define N 10
#define STARPOINT   1  
#define ENDPOINT    2  
#define BARRIER     3 
#define ROAD        0
//数组中1代表起点,2代表终点,0代表可以通过,3代表障碍物
int landscape[N][N] = {           
	{ 1, 0, 0, 3, 0, 3, 0, 0, 0, 0 },
	{ 0, 0, 3, 0, 0, 0, 0, 3, 0, 3 },
	{ 3, 0, 0, 0, 0, 3, 3, 3, 0, 3 },
	{ 3, 0, 3, 0, 0, 3, 0, 2, 0, 3 },
	{ 3, 0, 0, 0, 0, 3, 0, 0, 0, 3 },
	{ 3, 0, 0, 3, 0, 0, 3, 3, 0, 3 },
	{ 3, 0, 0, 0, 0, 3, 3, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 3, 3, 3, 0, 0, 3, 0, 3, 0, 3 },
	{ 3, 0, 0, 0, 0, 3, 3, 3, 0, 3 },
};
set<pair<int, int>>close_table;
pair<int, int>endpoint(3, 7);
vector<pair<int, int>>path;
bool UDless(pair<pair<int, int>, int> elem1, pair<pair<int, int>, int> elem2)
{
	return elem1.second > elem2.second;
}
vector<pair<pair<int, int>, int>>get_opentable(pair<int,int>current_point)
{
	vector<pair<pair<int, int>, int>>ve;
	if (current_point.first - 1 >= 0 && current_point.second - 1 >= 0 && landscape[current_point.first - 1][current_point.second - 1] != BARRIER
		&&close_table.find(pair<int, int>(current_point.first - 1, current_point.second - 1) )== close_table.end())
	{
		int k = abs(endpoint.first - current_point.first + 1) +
			abs(endpoint.second - current_point.second + 1)+14;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first - 1, current_point.second - 1), k);
		ve.push_back(cc);//左上
	}
	if (current_point.first - 1 >= 0 && landscape[current_point.first - 1][current_point.second] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first - 1, current_point.second)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first + 1) +
			abs(endpoint.second - current_point.second)+10;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first - 1, current_point.second), k);
		ve.push_back(cc);//正上
		
	}
	if (current_point.first - 1 >= 0 && current_point.second + 1 <N&& landscape[current_point.first - 1][current_point.second + 1] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first - 1, current_point.second + 1)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first + 1) +
			abs(endpoint.second - current_point.second - 1)+14;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first - 1, current_point.second + 1), k);
		ve.push_back(cc);//右上
	}
	if (current_point.second + 1 < N&& landscape[current_point.first][current_point.second + 1] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first, current_point.second + 1)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first) +
			abs(endpoint.second - current_point.second-1)+10;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first, current_point.second+1), k);
		ve.push_back(cc);//正右
	}
	if (current_point.first + 1 <N && current_point.second + 1 <N&& landscape[current_point.first + 1][current_point.second + 1] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first+1, current_point.second + 1)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first - 1) +
			abs(endpoint.second - current_point.second - 1) + 14;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first +1, current_point.second + 1), k);
		ve.push_back(cc);//右下
	}
	if (current_point.first + 1 <N && landscape[current_point.first + 1][current_point.second] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first + 1, current_point.second)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first - 1) +
			abs(endpoint.second - current_point.second ) + 10;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first + 1, current_point.second), k);
		ve.push_back(cc);//正下
	}
	if (current_point.first + 1 <N && current_point.second - 1 >= 0 && landscape[current_point.first + 1][current_point.second - 1] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first + 1, current_point.second - 1)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first - 1) +
			abs(endpoint.second - current_point.second + 1) + 14;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first  +1, current_point.second - 1), k);
		ve.push_back(cc);//左下
	}
	if (current_point.second - 1 >= 0 && landscape[current_point.first][current_point.second - 1] != BARRIER &&
		close_table.find(pair<int, int>(current_point.first , current_point.second - 1)) == close_table.end())
	{
		int k = abs(endpoint.first - current_point.first ) +
			abs(endpoint.second - current_point.second + 1) + 10;
		pair<pair<int, int>, int>cc(pair<int, int>(current_point.first, current_point.second - 1), k);
		ve.push_back(cc);//正左
	}
	sort(ve.begin(), ve.end(), UDless);
	return ve;
}


bool A_star_search(pair<int,int>startpoint)
{
	path.push_back(startpoint);
	close_table.insert(path.back());
	vector<pair<pair<int, int>, int>>open_table;
	vector<vector<pair<pair<int, int>, int>>>aa;
	open_table = get_opentable(startpoint);
	if (open_table.empty())
		return false;
	path.push_back(open_table.back().first);
	close_table.insert(path.back());
	open_table.pop_back();
	aa.push_back(open_table);
	while (!aa.empty())
	{
		open_table = get_opentable(path.back());
		if (!open_table.empty())
		{
			path.push_back((open_table.back()).first);
			close_table.insert(path.back());
			vector<pair<pair<int, int>, int>>::iterator it;
			for (it = open_table.begin(); it != open_table.end(); it++)
				if (landscape[(*it).first.first][(*it).first.second] == ENDPOINT)
				{
					path.push_back(endpoint);
					return true;
				}
			open_table.pop_back();
			aa.push_back(open_table);
		}
		if (open_table.empty())
		{
			
			while ((aa.back()).empty())
			{
				close_table.erase(path.back());
				path.pop_back();
				aa.pop_back();
				if (aa.empty())
					return false;
			}
			close_table.erase(path.back());
			path.pop_back();
			path.push_back(aa.back().back().first);
			close_table.insert(path.back());
			aa.back().pop_back();
		}
	}

}






int _tmain(int argc, _TCHAR* argv[])
{
	vector<pair<int, int>>::iterator it;
	if (A_star_search(pair<int, int>(0, 0)))
		for (it = path.begin(); it != path.end(); it++)
			cout << "(" << (*it).first << "," << (*it).second << ")" << endl;

	system("pause");
	return 0;
}

这是一个简易版本,不保证路径最短,后面我会实现一个最短路径的版本。

版权声明:

免责声明:文章转载自《A*搜索算法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇cocos2d-js 调试办法 断点调试 Android真机调试将xml文件由格式化变为压缩字符串下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

单阶多层检测器: SSD(一)

  对于物体检测任务, 第4章的Faster RCNN算法采用了两阶的检测架构, 即首先利用RPN网络进行感兴趣区域生成, 然后再对该区域进行类别的分类与位置的回归, 这种方法虽然显著提升了精度, 但也限制了检测速度。 YOLO算法利用回归的思想, 使用一阶网络直接完成了物体检测, 速度很快, 但是精度有了明显的下降。   在此背景下, SSD(Singl...

实验1:基于Weka的典型数据挖掘应用

一、实验目标 理解数据挖掘的基本概念,掌握基于Weka工具的基本数据挖掘(分类、回归、聚类、关联规则分析)过程。 二、实验内容 下载并安装Java环境(JDK 7.0 64位)。 下载并安装Weka 3.7版。 基于Weka的数据分类。 基于Weka的数据回归。 基于Weka的数据聚类。 基于Weka的关联规则分析。 三、实验步骤 1.下载并安装Jav...

信息摘要算法之五:HMAC算法分析与实现

MAC(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,兼容了MD和SHA算法的特性,并在此基础上加上了密钥。因此MAC算法也经常被称作HMAC算法。 1、HMAC概述 HMAC算法首先它是基于信息摘要算法的。目前主要集合了MD和SHA两大系列消息摘要算法。其中MD系列的算法有HmacMD2、HmacMD4、...

盘点一下数据平滑算法

本文参考来自于:http://blog.csdn.net/wwjiang_ustc/article/details/50732211   在自然语言处理中,经常要计算单词序列(句子)出现的概率估计。我们知道,算法在训练时,语料库不可能包含所有可能出现的序列。     因此,为了防止对训练样本中未出现的新序列概率估计值为零,人们发明了好多改善估计新序列出现概...

[转载]最小生成树-Prim算法和Kruskal算法

转载地址:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html  自己在学,感觉这个讲的很不错,就转载了。 Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点...

JAVA编程心得-JAVA实现CRC-CCITT(XMODEM)算法

CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 1 byte checksum CRC-16 CRC-16 (Modbus)CRC-16 (Sick)CRC-CCITT (XModem)CRC-CCITT (0xFFFF) CRC-CCITT...