以我个人的理解:

A*寻路算法是一种启发式算法,算法的核心是三个变量f,g,h的计算。g表示 从起点 沿正在搜索的路径 到 当前点的距离,h表示从当前点到终点的距离,而f=g+h,所以f越小,则经过当前点的最终路径长度也就越小。

算法当中,有两个辅助列表用来搜索路径。

搜索域(开启列表)和已搜索域(关闭列表)。其中搜索域用来存放待搜索的节点,已搜索域存放已经搜过的节点。

这两个列表的用法:

1、初始化:首先把起点放进搜索域。

2、从搜索域取出f最小的节点,分别遍历上下左右,左上,右下,左下,右上8个方向,并计算他们的f,g,h值,放进搜索域。

3、把当前节点从搜索域中删除,把当前节点放进已搜索域。进入第2步,循环。直到搜索域为空,或者找到终点。

那么重点的就是这个过程怎么实现。

用下面的图来做演示:

                    图1

图1中,绿色表示起点,红色表示终点,紫色表示墙。

1、计算起点的g,h,f,放进搜索域。

2、从搜索域取出f值最小的节点,8个方向搜索。(下 图2中蓝色部分)

3、从搜索域中删除当前节点,把当前节点放入已搜索域中。到第2步循环。

                   图2

                  图3

图3中橙黄色部分表示在 已搜索域 中。蓝色表示在 搜索域 中。

                  图4

                  图5

                  图6

........此处省略若干图。

                  最终图

过程大概就是这个过程。下面看代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <list>
#include <cmath>
#include <windows.h>
using namespace std; typedef struct node
{
node() //构造函数 初始化数据
{
x=y=0;
f=h=g=0;
parent=NULL;
}
int x,y; //坐标 这里的x对应下面的i,y对应j
double f,h,g; //g表示从原点到当前节点路线的长度,h表示当前节点到目标节点的长度,f=g+h表示从原点到目标点经过当前节点的路线长度
struct node *parent; //父节点
} Node; //节点结构体(每个节点表示一个正方形小格子) const int MAX=100;
const int LEN=10; //把地图分割成一个一个的正方形小格子,每个格子的长度为LEN
const char ROAD='*'; //最后输出的时候,'*'表示路线 char mmap[MAX][MAX]; //注意:'0'表示起点,'1'表示终点 int si,sj,ei,ej; //si,sj分别记录起点的x,y坐标,ei,ej分别记录终点的x,y坐标
int n,m;
int dx[8]= {-1,1,0,0,-1,1,-1,1}; //8个方向 上下左右,左上,右下,右上,左下
int dy[8]= {0,0,-1,1,-1,1,1,-1}; list<Node*> startList,endList; //startList表示搜索域,endList存储已搜索过的节点 Node *start=NULL; //起点指针 //判断节点指针node 是否 在列表mlist中
bool in_List(Node * node,list<Node*> mlist)
{
for(list<Node*>::iterator it=mlist.begin();it!=mlist.end();it++)
{
if((*it)->x==node->x&&(*it)->y==node->y)
{
return true;
}
}
return false;
} //从列表中获取f最小的节点指针
Node* getMinNode(list<Node*> mlist)
{
double mmin=1000000;
Node *pmmin=NULL;
for(list<Node*>::iterator it=mlist.begin(); it!=mlist.end(); it++)
{
if((*it)->f<mmin)
{
mmin=(*it)->f;
pmmin=(*it);
}
}
return pmmin;
} //从列表中删除节点指针
void del(Node *node,list<Node*> &mlist)
{
for(list<Node*>::iterator it=mlist.begin(); it!=mlist.end(); it++)
{
if((*it)==node)
{
mlist.erase(it);
return;
}
}
}
//向列表中添加节点指针
void add(Node *node,list<Node*> &mlist)
{
mlist.push_back(node);
return;
} //计算(x1,y1)到(x2,y2)的距离
double getDis(int x1,int y1,int x2,int y2)
{
double xx1=x1*LEN+LEN/2.0;
double yy1=y1*LEN+LEN/2.0;
double xx2=x2*LEN+LEN/2.0;
double yy2=y2*LEN+LEN/2.0;
return sqrt((xx1-xx2)*(xx1-xx2)+(yy1-yy2)*(yy1-yy2));
} //回溯寻找路径
void setRoad(Node *root)
{
while(root->parent!=NULL)
{
if(root->x==ei&&root->y==ej)
mmap[root->x][root->y]='1';
else
mmap[root->x][root->y]=ROAD;
root=root->parent;
}
} void work()
{
start=new Node;
start->parent=NULL;
start->f=0;
start->g=0;
start->h=0;
start->x=si;
start->y=sj;
add(start,startList);
while(!startList.empty())
{
Node *cur=getMinNode(startList); //从搜索列表中获取f最小的节点
if(cur==NULL)
{
cout<<"自动寻路失败"<<endl;
return;
}
add(cur,endList); //把当前节点放入已搜索过的列表中
del(cur,startList); //从搜索列表中删除当前节点
for(int k=0; k<8; k++) //8个方向搜索
{
int cx=cur->x+dx[k];
int cy=cur->y+dy[k]; if(cx<0||cy<0||cx>=n||cy>=m) //坐标越界
{
continue;
} else if(mmap[cx][cy]=='#') //是墙
continue; Node *now=new Node;
now->x=cx;
now->y=cy;
now->parent=cur;
now->g=cur->g+getDis(now->x,now->y,cur->x,cur->y);
now->h=getDis(now->x,now->y,ei,ej);
now->f=now->g+now->h; if(in_List(now,startList)||in_List(now,endList)) //是否在搜索列表或已搜索列表中
continue; add(now,startList); //添加到搜索列表中
if(cx==ei&&cy==ej) //如果当前节点是终点
{
setRoad(now); //回溯找路径 for(int i=0; i<n; i++) //输出地图
{
for(int j=0; j<m; j++)
{
if(mmap[i][j]==ROAD||mmap[i][j]=='0'||mmap[i][j]=='1') //如果是路径则输出颜色设置成绿色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN);
}
else //否则无色只以亮度显示
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY);
cout<<mmap[i][j]<<" ";
}
cout<<endl;
}
return;
}
} }
cout<<"自动寻路失败"<<endl;
return;
} int main()
{
while(cin>>n>>m)
{
si=sj=ei=ej=0;
startList.clear();
endList.clear(); for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
cin>>mmap[i][j];
if(mmap[i][j]=='0')
{
si=i;
sj=j;
}
else if(mmap[i][j]=='1')
{
ei=i;
ej=j;
}
}
}
work();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY);
}
return 0;
}

  

程序测试:

输入:

8 8
````#```
````#```
````#```
`0``#``1
````#```
````#```
```##```
```#````
10 8
````#```
``#`#```
``#`#```
``#`````
``#`##``
``#`#``#
`##`#``#
`###`##1
`0##`##`
####`#``

输出结果:

绿色表示路径。

A*寻路算法详解的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  3. 机器学习经典算法详解及Python实现--基于SMO的SVM分类器

    原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector  ...

  4. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  5. 【转】AC算法详解

    原文转自:http://blog.csdn.net/joylnwang/article/details/6793192 AC算法是Alfred V.Aho(<编译原理>(龙书)的作者),和 ...

  6. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  7. EM算法详解

    EM算法详解 1 极大似然估计 假设有如图1的X所示的抽取的n个学生某门课程的成绩,又知学生的成绩符合高斯分布f(x|μ,σ2),求学生的成绩最符合哪种高斯分布,即μ和σ2最优值是什么? 图1 学生成 ...

  8. Tarjan算法详解

    Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...

  9. 安全体系(二)——RSA算法详解

    本文主要讲述RSA算法使用的基本数学知识.秘钥的计算过程以及加密和解密的过程. 安全体系(零)—— 加解密算法.消息摘要.消息认证技术.数字签名与公钥证书 安全体系(一)—— DES算法详解 1.概述 ...

随机推荐

  1. javascript基础扫盲

    JavaScript基础扫盲 null和undefined 非十进制的表示方法 强制类型转换 运算 null和undefined null是一个是非来表示一个空对象的,故 typeof 的返回值是ob ...

  2. LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)

    很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...

  3. opencv学习HighGUI图形用户界面初步【1】

    HighGUI是图形用户界面模块.包括:1.输入与输出:2.视频捕捉:3.图形和视频的解码编码:4.图形交界面与接口. 由于opencv.hpp包含了core.objdetect.ingproc.ph ...

  4. JavaSE 学习笔记之Java概述(一)

    一.Java的三种技术架构: JAVAEE:Java Platform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发: JAVASE:Java Platfor ...

  5. 0919MYSQL中取当前周/月/季/年的第一天与最后一天

    http://blog.csdn.net/cleanfield/article/details/41447585 整理后的sql代码,全部可执行 #当年第一天: SELECT DATE_SUB(CUR ...

  6. VS的代码管理工具

    参考文章 可以从中知道修改代码段是要打开相关路径下的文档来修改 官方下载地址 百度云盘 如果项目中国有一些代码重复率非常高,可以把这些代码做成snippet代码段,简化成快捷键命令,加速开发

  7. POJ 2375

    BFS+强连通.输出max(缩点后出度为0的点数,缩点后入度为0的点数). #include <cstdio> #include <iostream> #include < ...

  8. poj--1274--The Perfect Stall(最大匹配)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21665   Accepted: 973 ...

  9. Sublime Text 2 界面主题 推荐 Flatland

    先搜索下THEME-FLATLAND 安装完后在preferences中选择settings-usr { "color_scheme": "Packages/Theme ...

  10. php pdo操作

    PDO(PHP Data Object) 是PHP 5 中加入的东西,是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,什么 p ...