《算法的乐趣》终于出版了


经过一年多的编写和准备,《算法的乐趣》终于出版了,4月中旬开始可以在京东、当当等网店购买,实体书店上架可能会慢一点。感谢图灵社区的各位老师的辛勤耕耘,也感谢《啊哈!算法》作者纪磊先生(啊哈磊),LinkedIn高级主任分析师王益先生,极光推送首席科学家黄鑫先生(飞林沙)为本书热情作序并给予充分的肯定。


序一

读《算法的乐趣》的乐趣超出了我的预料。

说到算法,大部分计算机专业的同学的第一反应估计是MIT出版社的经典教材《算法导论》(Introduction to Algorithms)。这是一本由浅入深的好书,堪称“神书”——别看书挺厚,但是对初学者来说很难弄懂的问题也娓娓道来,让人看一遍就明白;而且作者用最简单的英语词汇和句法写书,以至于世界各地的学生们,不需要英语很好,即可读懂原版。只是看完这本大部头之后,总有一些意犹未尽的感觉——对我们日常生活中常见的比如音乐播放器里以及电子游戏里的算法并没有太多介绍。而这些正是《算法的乐趣》中主要的部分。

在Amazon上,另外两本排名靠前的经典算法教材是Jon Kleinberg的《算法设计》(Algorithm Design)和Steven S. Skiena的《算法设计手册》(The Algorithm Design Manual)。这两本出自名家之手的教材和很多教材一样,按照算法的类型或者背后的设计思路来组织内容。这是教材应该做的,“授人以鱼不如授人以渔”,传授思路而不是算法本身是教材的写作目的。可是算法最有意思的地方首先在于算法本身,因为算法是为了解决实际问题而设计的,所以让大家认识到算法奥妙的自然顺序应该是先展示有趣的问题,再展示优雅的算法,最后归纳设计思路。而这正是《算法的乐趣》吸引人的地方。说到乐趣,总让我想起我学习和使用数学知识的经历。虽然我的学位是关于统计机器学习的,而且毕业后一直从事相关工作,但是我从小学一年级到博士第三年都对数学毫无兴趣,因为学校的老师和数学成绩好的同学都说不明白数学的用处,以至于我一直以为数学的作用只是锻炼和展示自己的聪明,博得老师的表扬,成为陈景润那样为国争光的英雄。而这些对我实在没有吸引力,而且我认为恐怕对绝大部分学生都没什么吸引力。

我认识到数学的价值,是因为在博士第三年把研究方向换到了统计机器学习。在读教材的时候,我曾想验证“数学无用”,所以费尽心力地试图写一个程序来判断一个64×64像素的图片里到底是数字“1”还是数字“9”,却发现无论如何也很难写一个有效的程序;可是利用教材里的数学知识却能设计和“训练”一个数学模型,准确地识别任意字符。因为体会到了数学的用处,我兴奋地用了一年的时间复习大学本科的数学课程,然后才读懂了人工智能的专业教材和论文。此后才有所创新,发表论文,到博士毕业。这整个过程用了三年,而效果超过了之前19年数学教育的效果。

在这个过程中,我自然而然地开始注意数学知识的前因(比如为什么人们会关注长度、面积,怎么会有人考虑勾股定理这样的规律)以及后果(今天的数学知识能给物理学和机器智能带来什么样的帮助),也开始归纳和了解各种数学系统背后的规律,能体会哥德尔定理阐述的意思。当然,也破除了“数学是各种科学之母”之类的迷信,数学当然不是“科学之母”,而是“科学之子”,是先有物理学、力学和天文学,才有的数学;先有应用场景后有工具,先有探索后有归纳。

算法也是如此。先有工程问题需要解决,算法是解法,设计算法是寻求解法。虽然算法作为一门科学是归纳寻求解法的思路,但学习这种归纳法的前提是能体会各种具体算法的用处和效果。意识到这一点,自然也就破除了诸如“学好数学才能学好算法”之类的迷信。而把算法解决的各种有趣问题罗列出来,把算法的可爱之处展示给愿意发现和体会生活中点滴乐趣的读者们,正是《算法的乐趣》在技术价值之外的一层社会价值。

十年前,当我们坐在课堂里学习算法的时候,我们学到的是如何用人脑寻求解法,然后把解法写成程序,让计算机照着执行去解决问题。这是“经典算法”。最近十几年,随着Internet产业的兴起,Internet服务在不断取代原来由人提供的服务,这就要求机器拥有一定程度上能取代人的“智能”。在搜索引擎、推荐系统和广告系统等各个领域里,类似上述“识别数字”的问题越来越多,而人工智能和机器学习的应用也越来越深入我们的生活。机器学习算法的设计目标和“经典算法”不同——不是让人来想解法,而是让计算机从数据归纳知识——有了这些知识,计算机就能自己寻求解法。

虽然经典算法和机器学习算法之间的差别大得如同一场革命,但是由经典而入机器学习的过程却是自然而然的。比如《算法的乐趣》中介绍的曲线拟合问题,就是supervised learning(有监督学习),而音乐播放器里常用的傅里叶变换和其他时域频域变换则是unsupervised learning(无监督学习)的技术基础,棋类游戏算法是博弈论和reinforcement learning(强化学习)的经典例子。我常见有朋友从读数学教材开始探索机器学习和人工智能算法,也常看到有人不堪忍受长时间缺乏乐趣的探索以至于半途而废。如果是这样,也许不如从《算法的乐趣》开始这个探索过程。

我曾经以为从乐趣出发阐述算法的书会从西方发芽,没想到先看到了一本中文书。这真超出了我的预料。

王益

LinkedIn高级主任分析师

序二

当图灵出版社的编辑找到我希望我为这本书写个序的时候,我和旁边的同事调侃了一句:又一本简版的《算法导论》要诞生了。但是我还是下载了附件阅读了这本书,当翻到目录的时候,我的兴趣就被燃起来了,转头和同事说,也许这是一本不错的书。

程序员到底需不需要学习算法?这个问题被争论的次数绝对不亚于“Java是不是最好的语言”“VIM和Emacs谁是最好的编辑器”“程序员是不是需要学习数学”。为了避免陷入这样的争论里,我们先对“算法”一词做个转换定义,什么是算法?下面我举几个我亲身经历的例子。

有一次我们发布了一个APP,在注册时要求用户输入自己的真实姓名,但是粗心的工程师忘记了要求用户填写自己的性别,更可怜的是在欢迎页上面明晃晃地写着“欢迎XXX先生注册XX网”,可是应用已经发布到了App Store,到底怎么办?有一位工程师提出了一个办法,我们根据已有的用户姓名和性别作为训练集,来预测新用户到底是男还是女,为了让这个错误尽快得到修复,我们使用了最简单的朴素贝叶斯分类算法,最终测试集上的预测准确率达到93%,也就是说我们解决了93%用户的体验问题。我把这类算法称为专业类算法,也就是招聘网站上算法工程师要求的算法,例如图像处理工程师、数据挖掘工程师等。

有一次我们有一个相似性搜索的需求,数据量不大,只有几万条的数据记录,没有必要用ES这样的搜索引擎。例如输入“长沙市”, 也希望可以找到“我爱湖南长沙”“沙市小吃”等,且不说这个需求是否合理,我们单纯来讨论这个问题的解决方案。工程师实现的第一版是将所有字的组合全部列举出来,然后在数据库里做like操作,性能无法接受。于是我们提出了另一种解决方案:将数据库中的每个词都拆成单字,做成集合,保存在缓存中。接下来只需要对集合做交集操作,以字为单位计算词与词之间的相似性,性能问题一下就解决了。这种解题思路在《编程珠玑》中屡见不鲜,这不足以称为具体的算法,几乎都是在梳理我们的逻辑,训练我们解决问题的能力,我把这类算法称为逻辑类算法,或者技巧类算法。

还有一次,我们有个需求是帮助用户做旅游的行程规划,其中的情况比较复杂,因为除了地理位置之外,还需要包含目的地的过往用户评价、所需耗时、不同城市的住宿花费等。但是如果我们仔细分析,可以基于产品设计去拆分问题。在在线部分,我们可以去使用基于路程的最短图路径算法,或者基于价格的贪心算法,也可以在综合排序处为用户选择使用了变形加权的最短图路径算法。在离线部分,由于图的节点和边都较少,可以使用穷举法来为用户找到几种不同类型的最优解。这些算法都是在《算法导论》和《数据结构》中有着详细讨论的算法,书中的每一个算法和数据结构都是作者多年来抽象总结出的通用思路,我称之为通用类算法。

再说一个最基本的,我们做一个网站允许用户发布状态,在高峰期并发量太大,数据库不堪重负,所以我们需要将用户的插入记录先存入到消息队列中,保证用户的正常使用,然后再落地到MySQL数据库中。大家都会想到选择队列这样一种先入先出的数据结构,这也属于一种算法。

通过上面的几个例子,你会不会觉得你的身边处处都是算法?那么到底什么是算法?我们看看标准的定义:能够对一定规范的输入,在有限时间内获得所要求的输出的一系列指令都叫作算法。这个定义太抽象了,让我们简单来说,算法其实就是解决问题的思路和办法。那么从这一点来说,你还会说算法不重要么?

那么为什么还会有很多学生,甚至已经工作了很久的朋友还会说大学学的东西没有意义,算法没有用呢?归根结底是因为大家不知道为什么学,或者说缺乏算法的场景化。我在读大学的时候,经常做一些简单的网站,用到的技术无外乎是最简单的对数据库的增删改查,当时最大的感觉就是算法没有用。后来随着工作的深入,我开始逐步地意识到算法的重要性,逐渐地把算法捡了起来。

这本书给我最大的惊喜是没有像一般的算法书一样单纯地去讲算法和数据结构本身,那样无论语言多风趣,只要一谈到关键的问题也会马上变得无趣起来。作者在每一章都给出了一个实际的问题,然后尝试用算法去解决这一个问题,没有局限于通用类算法,而是同时涵盖逻辑类算法、通用类算法和专业类算法,真正是在训练读者解决问题的能力,而解决问题的能力,正是任何一家公司所需人才的最核心的技能。

另外,我已经在幻想作者在下一本书里可以把工作中的实际场景列举出来,更进一步地讲述工作中的算法,让每一个在校学生都可以意识到算法对于未来工作的重要性,也让每一位从业者拍案叫绝:“原来这个问题可以这样解!”让人人谈算法,人人写算法,引发软件行业的全民算法潮。

黄鑫(飞林沙)

极光推送首席科学家


序三

如果说《啊哈!算法》是算法界的小白书,内容太少看得不过瘾,那么这本《算法的乐趣》或许可以带你一起牛逼一起飞。当我刚拿到书的目录的时候,我就很期待,因为终于有一本算法书可以系统地和大伙说一说这些我也很想与大伙说的伟大算法。

暴力盲目的搜索算法往往让计算机显得很笨甚至有点痴呆,如果你想设计一个“狡猾”的程序,那么本书中的搜索剪枝、A*寻径、博弈树以及遗传算法等将给你带来启发。快速傅里叶变换,这么霸气而又高大上的名字,其实在我们生活中的应用随处可见,家中的Wi-Fi、智能手机、电话、路由器等几乎所有内置计算机系统的东西都会以各种方式使用这个算法。RLE数据压缩算法,在文档、视频、音乐、数据存储、云计算、数据库等几乎所有应用中都有着广泛的运用。压缩算法令系统更有效,成本更低。再来说密码学算法中非常重要的RSA算法,如果没有这些算法,互联网就会变得不安全,电子交易就不会如此可信。

好玩的算法还有很多很多,历法与二十四节气的计算、华容道、井字棋、黑白棋、五子棋以及俄罗斯方块……你会惊讶地发现,再简单不过的事情背后,都藏着算法的神奇背影。不妨将本书放在案头慢慢品读,你将能看到算法如何深入我们的日常生活,如何重塑我们的世界。

你准备好了吗?接下来,这个世界算法将接管一切。

啊哈磊

《啊哈!算法》作者



本书的序和部分试读章节可在CSDN的资源下载部分下载,以下是本书目录的三级标题展开:


第1章 程序员与算法
  • 1.1 什么是算法
  • 1.2 程序员必须要会算法吗
    • 1.2.1 一个队列引发的惨案
    • 1.2.2 我的第一个算法
  • 1.3 算法的乐趣在哪里
  • 1.4 算法与代码
  • 1.5 总结
  • 1.6 参考资料
阅读
第2章 算法设计的基础
  • 2.1 程序的基本结构
    • 2.1.1 顺序执行
    • 2.1.2循环结构
    • 2.1.3 分支和跳转结构
  • 2.2算法实现与数据结构
    • 2.2.1 基本数据结构在算法设计中的应用
    • 2.2.2 复杂数据结构在算法设计中的应用
  • 2.3 数据结构和数学模型与算法的关系
  • 2.4 总结
  • 2.5 参考资料
 
第3章 算法设计的常用思想
  • 3.1 贪婪法
    • 3.1.1 贪婪法的基本思想
    • 3.1.2 贪婪法的例子:0-1背包问题
  • 3.2 分治法
    • 3.2.1 分治法的基本思想
    • 3.2.2 递归和分治,一对好朋友
    • 3.2.3分治法的例子:大整数karatsuba乘法算法
  • 3.3 动态规划
    • 3.3.1动态规划的基本思想
    • 3.3.2 动态规划法的例子:字符串的编辑距离
  • 3.4 解空间的穷举搜索
    • 3.4.1解空间的定义
    • 3.4.2穷举解空间的策略
    • 3.4.3 穷举搜索的例子:Google方程式
  • 3.5 总结
  • 3.6 参考资料
 
第4章 阿拉伯数字与中文数字
  • 4.1 中文数字的特点
    • 4.1.1 中文数字的权位和小节
    • 4.1.2 中文数字的零
  • 4.2 阿拉伯数字转中文数字
    • 4.2.1 一个转换示例
    • 4.2.2 转换算法设计
    • 4.2.3 算法实现
    • 4.2.4中文大写数字
  • 4.3 中文数字转阿拉伯数字
    • 4.3.1 转换的基本方法
    • 4.3.2 算法实现
  • 4.4 数字转换的测试用例
  • 4.5 参考资料
 
第5章 三个水桶等分8升水的问题
  • 5.1 问题求解与思路
  • 5.2 建立数学模型
    • 5.2.1 状态的数学模型与状态树
    • 5.2.2 倒水动作的数学模型
  • 5.3 搜索算法
    • 5.3.1 状态树的遍历
    • 5.3.2 剪枝和重复状态判断
  • 5.4 算法实现
  • 5.5 总结
  • 5.6 参考资料
 
第6章 妖怪与和尚过河问题
  • 6.1 问题与求解思路
  • 6.2 建立数学模型
    • 6.2.1 状态的数学模型与状态树
    • 6.2.2 过河动作的数学模型
  • 6.3 搜索算法
    • 6.3.1 状态树的遍历
    • 6.3.2 剪枝和重复状态判断
  • 6.4 算法实现
  • 6.5 总结
  • 6.6 参考资料
 
第7章 稳定匹配与舞伴问题
  • 7.1 稳定匹配问题
    • 7.1.1 什么是稳定匹配
    • 7.1.2 Gale-Shapley算法原理
  • 7.2 Gale-Shapley算法的应用实例
    • 7.2.1算法实现
    • 7.2.2 改进优化:空间换时间
  • 7.3 有多少稳定匹配
    • 7.3.1 穷举所有的完美匹配
    • 7.3.2 不稳定因素的判断算法
    • 7.3.3 穷举的结果
  • 7.4 二部图与二分匹配
    • 7.4.1最大匹配与匈牙利算法
    • 7.4.2 带权匹配与Kuhn-Munkres算法
  • 7.5 总结
  • 7.6 参考资料
阅读
第8章 爱因斯坦的思考题
  • 8.1 问题的答案
  • 8.2 分析问题的数学模型
    • 8.2.1 基本模型定义
    • 8.2.2 线索模型定义
  • 8.3 算法设计
    • 8.3.1 穷举所有的组合结果
    • 8.3.2 利用线索判定结果的正确性
  • 8.4 总结
  • 8.5 参考资料
 
第9章 项目管理与图的拓扑排序
  • 9.1 AOV网和AOE网
  • 9.2 拓扑排序(Topological Sorting)
    • 9.2.1 拓扑排序的基本过程
    • 9.2.2 按照活动开始时间排序
  • 9.3 关键路径算法
    • 9.3.1 什么是关键路径
    • 9.3.2 计算关键路径的算法
  • 9.4 总结
  • 9.5 参考资料
 
第10章 RLE行程长度压缩算法与PCX图像格式
  • 10.1 RLE压缩算法
    • 10.1.1 连续重复数据的处理
    • 10.1.2连续非重复数据的处理
    • 10.1.3 算法实现
  • 10.2 RLE与PCX图像文件格式
    • 10.2.1 PCX文件格式
    • 10.2.2 PCX_RLE算法
    • 10.2.3 256色PCX文件的解码和显示
  • 10.3 总结
  • 10.4 参考资料
 
第11章 算法与历法
  • 11.1 格里历(公历)生成算法
    • 11.1.1 格里历的历法规则
    • 11.1.2 今天星期几
    • 11.1.3 生成日历的算法
    • 11.1.4 日历变更那点事儿
  • 11.2 二十四节气的天文学计算
    • 11.2.1 二十四节气的起源
    • 11.2.2 二十四节气的天文学定义
    • 11.2.3 VSOP-82/87行星理论
    • 11.2.4 误差修正-章动
    • 11.2.5 误差修正-光行差
    • 11.2.6 用牛顿迭代法计算二十四节气
  • 11.3 农历朔日(新月)的天文学计算
    • 11.3.1 如月合朔的天文学定义
    • 11.3.2 ELP-2000/82月球理论
    • 11.3.3 误差修正-地球轨道离心率修正
    • 11.3.4 误差修正-黄经摄动
    • 11.3.5 月球地心视黄经和最后的修正-地球章动
    • 11.3.6 用牛顿迭代法计算日月合朔
  • 11.4 农历的生成算法
    • 11.4.1 中国农历的起源与历法规则
    • 11.4.2 中国农历的推算
    • 11.4.3 一个简单的“年历”
  • 11.5 总结
  • 11.6 参考资料
 
第12章 实验数据与曲线拟合
  • 12.1 曲线拟合
    • 12.1.1 曲线拟合的定义
    • 12.1.2 简单线性数据拟合的例子
  • 12.2 最小二乘法曲线拟合
    • 12.2.1 最小二乘法原理
    • 12.2.2 高斯消元法求解方程组
    • 12.2.3 最小二乘法解决“速度与加速度”实验
  • 12.3 三次样条曲线拟合
    • 12.3.1 插值函数
    • 12.3.2 样条函数的定义
    • 12.3.3 边界条件
    • 12.3.4 推导三次样条函数
    • 12.3.5 追赶法求解方程组
    • 12.3.6 三次样条曲线拟合算法实现
    • 12.3.7 三次样条曲线拟合的效果
  • 12.4 总结
  • 12.5 参考资料
 
第13章 非线性方程与牛顿迭代法
  • 13.1非线性方程求解的常用方法
    • 13.1.1 公式法
    • 13.1.2 二分逼近法
  • 13.2 牛顿迭代法的数学原理
  • 13.3 用牛顿迭代法求解非线性方程的实例
    • 13.3.1 导函数的求解与近似公式
    • 13.3.2 算法实现
  • 13.4 参考资料
 
第14章 计算几何与计算机图形学
  • 14.1.1 点与矩形的关系
  • 14.2 直线生成算法
    • 14.2.1 什么是光栅图形扫描转换
    • 14.2.2 数值微分法(DDA法)
    • 14.2.3 Bresenham算法
    • 14.2.4 对称直线生成算法(改进的Bresenham算法)
    • 14.2.6 其他直线生成算法
  • 14.2.5 两步算法
  • 14.3 圆生成算法
    • 14.3.2 中点画圆法
    • 14.3.3 改进的中点画圆法-Bresenham算法
    • 14.3.4 正负判定画圆法
  • 14.3.1 圆的八分对称性
  • 14.1 计算几何的基本算法
    • 14.1.2 点与圆的关系
    • 14.1.3 矢量的基础知识
    • 14.1.4 点与直线的关系
    • 14.1.5 直线与直线的关系
    • 14.1.6 点与多边形的关系
 
第15章 音频频谱和均衡器与傅立叶变换算法
  • 15.1 实时频谱显示的原理
  • 15.2 离散傅立叶变换(DFT)
    • 15.2.1 什么是傅立叶变换
    • 15.2.2 傅立叶变换原理
    • 15.2.3 快速傅立叶变换的算法实现
  • 15.3 傅立叶变换与音频播放的实时频谱显示
    • 15.3.1  频域数值的特点分析
    • 15.3.2  从音频数据到功率频谱
    • 15.3.3 音频播放时实时频谱显示的例子
  • 15.4 破解电话号码的小把戏
    • 15.4.1 拨号音的频谱分析
    • 15.4.2 根据频谱数据反推电话号码
  • 15.5 离散傅立叶逆变换(IDFT)
    • 15.5.1 快速傅立叶逆变换(IFFT)的推导
    • 15.5.2 快速傅立叶逆变换(IFFT)的算法实现
  • 15.6 利用傅立叶变换实现频域均衡器
    • 15.6.1 频域均衡器的实现原理
    • 15.6.2 频域信号的增益与衰减
    • 15.6.3 均衡器的实现――仿Foobar的18段均衡器
  • 15.7 总结
  • 15.8 参考资料
 
第16章 全局最优解与遗传算法
  • 16.1 遗传算法的原理
    • 16.1.1 遗传算法的基本概念
    • 16.1.2 遗传算法的处理流程
  • 16.2 遗传算法求解“0-1背包问题”
    • 16.2.1 基因编码和种群初始化
    • 16.2.2 适应度函数
    • 16.2.3 选择算子设计与轮盘赌算法
    • 16.2.4 交叉算子设计
    • 16.2.5 变异算子设计
    • 16.2.6 这就是遗传算法
  • 16.3 总结
  • 16.4 参考资料
 
第17章 计算器程序与大整数计算
  • 17.1 哦,溢出了,出洋相的计算器程序
  • 17.2 大整数计算的原理
    • 17.2.1 大整数加法
    • 17.2.2 大整数减法
    • 17.2.3 大整数乘法
    • 17.2.4 大整数除法与模
    • 17.2.5 大整数乘方运算
  • 17.3 大整数类的使用
    • 17.3.1 与Windows的计算器程序一决高下
    • 17.3.2 最大公约数和最小公倍数
    • 17.3.3 用扩展欧几里德算法求模的逆元
  • 17.4 总结
  • 17.5 参考资料
 
第18章 RSA算法-加密与签名
  • 8.1 RSA算法的开胃菜
    • 18.1.1 将模幂运算转化为模乘运算
    • 18.1.2 模乘运算与“蒙哥马利算法”
    • 18.1.3 模幂算法
    • 18.1.4 素数检验与“米勒-拉宾算法”
  • 18.2 RSA加密算法原理
    • 18.2.1 RSA算法的数学理论
    • 18.2.2 加密和解密算法
    • 18.2.3 RSA算法的安全性
  • 18.3 数据块分组加密
    • 18.3.1 字节流与大整数的转换
    • 18.3.2 PCKS与OAEP加密填充模式
    • 18.3.3 数据加密算法实现
    • 18.3.4 数据解密算法实现
  • 18.4 RSA签名与身份验证
    • 18.4.1 RSASSA-PKCS与RSASSA-PSS签名填充模式
    • 18.4.2 签名算法实现
  • 18.5 总结
  • 18.6 参考资料
 
第19章 数独游戏
  • 19.1 数独游戏的规则与技巧
    • 19.1.1 数独游戏的规则
    • 19.1.2 数独游戏的常用技巧
  • 19. 2 计算机求解数独问题
    • 19.2.1 建立问题的数学模型
    • 19.2.2 算法实现
    • 19.2.3 与传统穷举方法的结果对比
  • 19. 3 关于数独的趣味话题
    • 19.3.1 数独游戏有多少终盘
    • 19.3.2 史上最难的数独游戏
  • 19. 4 总结
  • 19. 5 参考资料
 
第20章 华容道游戏
  • 20.1 华容道游戏介绍
  • 20.2 自动求解的算法原理
    • 20.2.1 定义棋盘的局面
    • 20.2.2 算法思路
  • 20.3 自动求解的算法实现
    • 20.3.1 棋局状态与Zobrist哈希算法
    • 20.3.2 重复棋局和左右镜像的处理
    • 20.3.3 正确结果的判断条件
    • 20.3.4 武将棋子的移动
    • 20.3.5 棋局的搜索算法
  • 20.4 总结
  • 20.5 参考资料
 
第21章 A*寻径算法
  • 21.1 寻径算法演示程序
  • 21.2 Dijkstra算法
    • 21.2.1 Dijkstra算法原理
    • 21.2.2 Dijkstra算法实现
    • 21.2.3 Dijkstra算法演示程序
  • 21.3 带启发的搜索算法——A*算法
    • 21.3.1 A*算法原理
    • 21.3.2 常用的距离评估函数
    • 21.3.3 A*算法实现
  • 21.4 总结
  • 21.5 参考资料
 
第22章 俄罗斯方块游戏
  • 22.1 俄罗斯方块游戏规则
  • 22.2 俄罗斯方块游戏人工智能的算法原 理
    • 22.2.1 影响评价结果的因素
    • 22.2.2 常用的俄罗斯方块游戏人 工智能算法
    • 22.2.3 Pierre Dellacherie评估算 法
  • 22.3 Pierre Dellacherie算法实现
    • 22.3.1 基本数学模型和数据结构 定义
    • 22.3.2 算法实现
  • 22.4 总结
  • 22.5 参考资料
 
第23章 博弈树与棋类游戏
  • 23.1 棋类游戏的AI
    • 23.1.1 博弈与博弈树
    • 23.1.2 极大极小值搜索算法
    • 23.1.3 负极大极搜索算法
    • 23.1.4 “α-β”剪枝算法
    • 23.1.5 估值函数
    • 23.1.6 置换表与哈希函数
    • 23.1.7 开局库与终局库
  • 23.2 井字棋——最简单的博弈游戏
    • 23.2.1 棋盘与棋子的数学模型
    • 23.2.2 估值函数与估值算法
    • 23.2.3 如何产生走法(落子方法)
  • 23.3 奥赛罗棋(黑白棋)
    • 23.3.1 棋盘与棋子的数学模型
    • 23.3.2 估值函数与估值算法
    • 23.3.3 搜索算法实现
    • 23.3.4 最终结果
  • 23.4 五子棋 
    • 23.4.1 棋盘与棋子的数学模型
    • 23.4.2 估值函数与估值算法
    • 23.4.3 搜索算法实现
    • 23.4.4 最终结果
  • 23.5 总结 
  • 23.6 参考资料
 
附录A 算法设计的常用技巧
  • A.1 数组下标处理
  • A.2 一重循环实现两重循环的功能
  • A.3 棋盘(迷宫)类算法方向遍历
  • A.4 代码的一致性处理技巧
  • A.5 链表和数组的配合使用
  • A.6 “以空间换时间”的常用技巧
  • A.7 利用表驱动避免长长的switch-case  
 
附录B 一个棋类游戏的设计框架 
  • B.1 代码框架的整体结构 
  • B.2 代码框架的使用方法

猜你喜欢

转载自blog.csdn.net/orbit/article/details/45204239
今日推荐