A*在游戏设计中有它很典型的用法,是人工智能在游戏中的代表。 
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚 
A*算法,我看还是先说说何谓启发式算法。 

一、何谓启发式搜索算法: 
在说它之前先提提状态空间搜索。状态空间搜索,如果按专业点的说 
法就是将问题求解过程表现为从 初始状态到目标状态寻找这个路径的 
过程。通俗点说,就是在解一个问题时,找到一条解题的过程可以从 
求解的开始到问题的结果(好象并不通俗哦)。由于求解问题的过程 
中分枝有很多,主要是求解过程中求 解条件的不确定性,不完备性造 
成的,使得求解的路径很多这就构成了一个图,我们说这个图就是状 
态空 间。问题的求解实际上就是在这个图中找到一条路径可以从开始 
到结果。这个寻找的过程就是状态空间搜索。 
常用的状态空间搜索有深度优先和广度优先。广度优先是从初始状态 
一层一层向下找,直到找到目标 为止。深度优先是按照一定的顺序前 
查找完一个分支,再查找另一个分支,以至找到目标为止。这两种算 
法在数据结构书中都有描述,可以参看这些书得到更详细的解释。 
前面说的广度和深度优先搜索有一个很大的缺陷就是他们都是在一个 
给定的状态空间中穷举。这在状 态空间不大的情况下是很合适的算法 
,可是当状态空间十分大,且不预测的情况下就不可取了。他的效率 
实在太低,甚至不可完成。在这里就要用到启发式搜索了。 
启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估, 
得到最好的位置,再从这个位置 进行搜索直到目标。这样可以省略 
大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价 
是十分重要的。采用了不同的估价可以有不同的效果。我们先看看 
估价是如何表示的。 
启发中的估价是用估价函数表示的,如: 
f(n) = g(n) + h(n) 
其中f(n) 是节点n的估价函数,g(n)实在状态空间中从初始节点到 
n节点的实际代价,h(n)是从n到目 标节点最佳路径的估计代价。在 
这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。如果说 
详细点,g(n)代表了搜索的广度的优先趋势。但是当h(n) >> g(n) 
时,可以省略g(n),而提高效率。这些就深了, 不懂也不影响啦! 
我们继续看看何谓A*算法。 

二、初识A*算法: 
启发式搜索其实有很多的算法,比如:局部择优搜索法、最好优先搜索 
法等等。当然A*也是。这些算法 都使用了启发函数,但在具体的选取 
最佳搜索节点时的策略不同。象局部择优搜索法,就是在搜索的过程 
中 选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,而一直得搜 
索下去。这种搜索的结果很明显,由于舍 弃了其他的节点,可能也把 
最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不 
一定是全局 的最佳。最好优先就聪明多了,他在搜索时,便没有舍弃 
节点(除非该节点是死节点),在每一步的估价中 都把当前的节点和 
以前的节点的估价值比较得到一个“最佳的节点”。这样可以有效的 
防止“最佳节点”的 丢失。那么A*算法又是一种什么样的算法呢? 
其实A*算法也是一种最好优先的算法。只不过要加上一些约束 条件 
罢了。由于在一些问题求解时,我们希望能够求解出状态空间搜索的 
最短路径,也就是用最快的方法求 解问题,A*就是干这种事情的! 
我们先下个定义,如果一个估价函数可以找出最短的路径,我们称之 
为可采 纳性。A*算法是一个可采纳的最好优先算法。A*算法的估价 
函数可表示为: 
f'(n) = g'(n) + h'(n) 
这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值,h'(n)是 
n到目标的最断路经的启发值。由 于这个f'(n)其实是无法预先知道的 
,所以我们用前面的估价函数f(n)做近似。g(n)代替g'(n),但 
g(n)>=g'(n) 才可(大多数情况下都是满足的,可以不用考虑), 
h(n)代替h'(n),但h(n)<=h'(n)才可(这一点特别的重 要)。可以 
证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。 
我们说应用这种估价函数的 最好优先算法就是A*算法。哈!你懂了吗? 
肯定没懂!接着看! 

举一个例子,其实广度优先算法就是A*算法的特例。其中g(n)是节点 
所在的层数,h(n)=0,这种h(n)肯 定小于h'(n),所以由前述可知广 
度优先算法是一种可采纳的。实际也是。当然它是一种最臭的A*算法。 

再说一个问题,就是有关h(n)启发函数的信息性。h(n)的信息性通俗 
点说其实就是在估计一个节点的值 时的约束条件,如果信息越多或约 
束条件越多则排除的节点就越多,估价函数越好或说这个算法越好。 
这就 是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0, 
一点启发信息都没有。但在游戏开发中由于实 时性的问题,h(n)的 
信息越多,它的计算量就越大,耗费的时间就越多。就应该适当的减 
小h(n)的信息,即 减小约束条件。但算法的准确性就差了,这里就 
有一个平衡的问题。可难了,这就看你的了! 

好了我的话也说得差不多了,我想你肯定是一头的雾水了,哈哈! 
你还是找一本人工智能的书仔细看看吧!我这几百字是不足以将A* 
算法讲清楚的。只是起到抛砖引玉的作用 希望大家热情参与! 
预知A*算法的应用,请看姊妹篇《深入A*算法》

http://liyanblog.cn/articles/2012/09/19/1348045903617.html

A*算法的更多相关文章

  1. B树——算法导论(25)

    B树 1. 简介 在之前我们学习了红黑树,今天再学习一种树--B树.它与红黑树有许多类似的地方,比如都是平衡搜索树,但它们在功能和结构上却有较大的差别. 从功能上看,B树是为磁盘或其他存储设备设计的, ...

  2. 分布式系列文章——Paxos算法原理与推导

    Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难. 网上有很多讲解Paxos算法的文章,但是质量参差不齐.看了很多关于Paxos的资 ...

  3. 【Machine Learning】KNN算法虹膜图片识别

    K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  4. 红黑树——算法导论(15)

    1. 什么是红黑树 (1) 简介     上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...

  5. 散列表(hash table)——算法导论(13)

    1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...

  6. 虚拟dom与diff算法 分析

    好文集合: 深入浅出React(四):虚拟DOM Diff算法解析 全面理解虚拟DOM,实现虚拟DOM

  7. 简单有效的kmp算法

    以前看过kmp算法,当时接触后总感觉好深奥啊,抱着数据结构的数啃了一中午,最终才大致看懂,后来提起kmp也只剩下“奥,它是做模式匹配的”这点干货.最近有空,翻出来算法导论看看,原来就是这么简单(先不说 ...

  8. 神经网络、logistic回归等分类算法简单实现

    最近在github上看到一个很有趣的项目,通过文本训练可以让计算机写出特定风格的文章,有人就专门写了一个小项目生成汪峰风格的歌词.看完后有一些自己的小想法,也想做一个玩儿一玩儿.用到的原理是深度学习里 ...

  9. 46张PPT讲述JVM体系结构、GC算法和调优

    本PPT从JVM体系结构概述.GC算法.Hotspot内存管理.Hotspot垃圾回收器.调优和监控工具六大方面进行讲述.(内嵌iframe,建议使用电脑浏览) 好东西当然要分享,PPT已上传可供下载 ...

  10. 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法

    若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...

随机推荐

  1. c#面向对象基础技能——学习笔记(五)委托技术在开发中的应用

    委托 delegate 1.是一种全新的面向对象语言的特性: 2.开发事件驱动程序变得非常简单: 3.简化多线程难度. 理解委托:可以理解成一个方法的指针.(接收的变量是方法) 步骤: 1.声明委托, ...

  2. Windows下删除.svn文件夹的最简易方法

    建立一个文本文件,取名为kill-svn-folders.reg(扩展名由txt改为reg),内容如下: Windows Registry Editor Version 5.00 [HKEY_LOCA ...

  3. Yii 2.x Behavior - 类图

    yii\base\Component  继承这个类的类都具备扩展行为的能力

  4. php调用web service接口(.net开发的接口)

    实例代码1: try { $this->soapClientObj = new SoapClient(self::URL . '?wsdl', array('connection_timeout ...

  5. 如何实现一个php框架系列文章【2】实现类的自动加载

    根据前一篇文章的设计原则,我们暂时把php文件分为3类,类名和文件名都遵守如下约定.   类名 文件名 路径 模型类m {$app}Mod  {$app}.mod.php {$app}/model   ...

  6. 用Fiddler模拟低速网络环境

    有时候宽频网路用习惯了… 在开发的过程就比较少去考虑最佳化的问题… 但当有人反应说「你的网页好慢」甚至当网路速度慢,会造成你的网页跳出什么啊哩不哒的bug时要如何重现呢? 我们可以用Fiddler 这 ...

  7. 如何在Node.js中合并两个复杂对象

    通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...

  8. JavaScript中数据类型转换总结

    JavaScript中数据类型转换总结 在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = " ...

  9. heartbeat在yum系发行版本的处理资料

    centos 安装包[rpm]和光盘iso文件 http://mirror.centos.org/centos/ 对应如上包的代码 http://vault.centos.org/ git.cento ...

  10. Android事件分发机制浅谈(三)--源码分析(View篇)

    写事件分发源码分析的时候很纠结,网上的许多博文都是先分析的View,后分析ViewGroup.因为我一开始理解的时候是按我的流程图往下走的,感觉方向很对,单是具体分析的时候总是磕磕绊绊的,老要跳到Vi ...