以我个人的理解:

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. python第十一周:RabbitMQ、Redis

    Rabbit Mq消息队列 RabbitMQ能为你做些什么? 消息系统允许软件.应用相互连接和扩展.这些应用可以相互链接起来组成一个更大的应用,或者将用户设备和数据进行连接.消息系统通过将消息的发送和 ...

  2. NET 爬虫

    最近经常听说或者接触关于网络爬虫的问题,只是一直看到被人写的代码.而没有真正的做过实践, 昨天做了一下尝试,其中采用网络流行的扩展类库 http://html-agility-pack.net/?z= ...

  3. 【codeforces 793B】Igor and his way to work

    [题目链接]:http://codeforces.com/contest/793/problem/B [题意] 给一个n*m大小的方格; 有一些方格可以走,一些不能走; 然后问你从起点到终点,能不能在 ...

  4. RabbitMQ学习总结(1)——基础概念详细介绍

    一.基础概念详细介绍 1.引言 你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用.通讯的问题而苦恼.挣扎?如果是,那么恭喜你,消息服务让你可以很轻松 ...

  5. [置顶] Java Web学习总结(24)——SSM(Spring+SpringMVC+MyBatis)框架快速整合入门教程

    1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One  ...

  6. XHXJ's LIS

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

  7. 草草搞了个SERVLET的注册登陆功能

    按书来的,学习阶段,一切都好新奇..至少对比于DJANGO,好像复杂点点,但HTTP的东东,是相通的哈. package cc.openhome.controller; import java.io. ...

  8. Linux用户和组的管理

    一.概述: 1.Linux下的三类用户: (1).超级用户(root)具有操作系统的一切权限UID值均为0 (2).普通用户具有操作系统有限的权限UID值500~6000 (3).伪用户是为了方便系统 ...

  9. 《游戏脚本的设计与开发》-(RPG部分)3.8 通过脚本来自由控制游戏(一)

    注意:本系列教程为长篇连载无底洞.半路杀进来的朋友,假设看不懂的话.请从第一章開始看起.文章文件夹请点击以下链接. http://blog.csdn.net/lufy_legend/article/d ...

  10. SQL SERVER读书笔记:TempDB

    每次SQL SERVER启动的时候,会重新创建. 用于 0.临时表 1.排序 2.连接(merge join,hash join) 3.行版本控制 临时表与表变量的区别: 1)表变量是存储在内存中的, ...