python汉诺塔_汉诺塔递归算法/搬金盘的婆罗门 - Python实现

30dd72e2663f682c040be8d0c81bede9.png

汉诺塔递归算法/搬金盘的婆罗门 - Python实现

版权声明
本文节选自作者本人的图书《Python编程基础及应用》,高等教育出版社。本文可以在互联网上自由转载,但必须:注明出处(作者:海洋饼干叔叔)并包含指向本页面的链接。本文不可以以纸质出版为目的进行改编、摘抄。本书同名免费MOOC《Python编程基础及应用》在哔哩哔哩(B站)热播,作者带着你学。

17.1 汉诺塔问题

法国数学家爱德华·卢卡斯曾转述过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根金刚石柱。印度教的主神梵天在创造世界的时候,在其中一根石柱上从下到上的穿好了由大到小的64块金盘,这就是所谓的汉诺塔 - Hanoi Tower。

按照梵天的命令,不论白天黑夜,总有一个婆罗门僧侣在按照下面的规则移动这些金盘:一次只移动一个盘,不管在哪根柱上,小盘必须在大盘上面。僧侣们预言,当所有的金盘都从梵天穿好的那根柱上移到另外一根柱上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。

17.1.1 求解

如下图所示的5个盘的汉诺塔问题,其总任务将A柱上的n = 5个盘移至C柱。要实现这个总任务并且保证移盘过程中小盘始终在大盘上面,整个过程分三步实现。第1步:我们必须先将n - 1 = 4个黑盘从A柱移至B柱。在第1步的执行过程当中,为了保证规则的贯彻,显然,必须借助于C柱作为中转柱才能完成。

第1步所做的工作可描述为:借助中转柱C, 将n-1=4个盘从A移至B

c1621d444bf0e8031d6597badf9fb63a.png

​ 现在,最大的白盘在A柱上,C柱是空的。可实施第2步:将A柱上的大盘取下,移至C柱

7b1cd19a0493f7070b7eba92298a4b9c.png

接下来,我们要做的是第3步: 借助中转柱A,将B柱上的n - 1 = 4个盘移至C柱。此时,C柱上虽然已经有了一个盘,但由于此盘是最大的,所以只要移动过程中不搬动C柱上的原有大盘,可以忽略其存在。

026dc56923bf54526b4c2c1ea4ed09c5.png

现在,我们试图总结一下总任务及其三个子任务:

总任务: 将 n = 5个盘从A柱移至C柱,以B柱为中转柱

不难看出,除了柱子不同,子任务3同子任务1所做的工作是一样的,都是把 n - 1 个盘从一个柱移至另一个柱。同时,子任务1,3与总任务之间也极其相似,除了需要移动的盘子数量差异外。

我们称,将n - 1个盘子从A移至B的汉诺塔问题,与原问题 - 即“将n个盘子从A移至C的汉诺塔问题”的性质完全相同,区别仅在于问题的规模 - 需要移动的盘子数量稍小。我也称为前者是原问题的子问题。

如果我们能将n - 1 = 4个盘子从A移至B,从B移至C,那么n = 5个盘子的汉诺塔问题可解。那么如何求解4个盘子的汉诺塔问题呢? 聪明的读者已经有了答案。

子问题: 将 n’ = 4个盘从A柱移至B柱,以C柱为中转柱

​ 下面的图展示了这一过程:

4997dac206064bcc1450f334a05701c9.png

b17ef9748dd32c3f9dad1c9a4a9cd730.png

上面的分析可以看出,5盘汉诺塔问题可以通过求解4盘汉诺塔问题来解决,4盘汉诺塔问题可以通过求解3盘汉诺塔问题来解决。同理,3盘汉诺塔问题可以通过求解2盘汉诺塔问题来解决,2盘汉诺塔问题可以通过求解一盘汉诺塔问题来解决。而一盘汉诺塔问题,由于问题的规模足够小,可直接解决:把盘从原柱搬至目标柱即可。所以在前表中,我们称其为“简单任务”。

17.1.2 递归算法

根据前一小节描述的算法思想,我们可以写出汉诺塔问题求解的递归算法。

#BasicHanoi.py
def hanoi(n, a, b, c):if n == 1:movements.append(a + " --> " + c)else:hanoi(n - 1, a, c, b)movements.append(a + " --> " + c)hanoi(n - 1, b, a, c)movements = []
hanoi(5, 'A', 'B', 'C')
print("Steps count:",len(movements))
print("The first 3 steps are:", movements[:3])

函数hanoi(n,a,b,c)用于生成以b为中转柱,将n个金盘从a移至c的移盘序列。可以看到,这个递归函数的执行过程跟前节的总任务-子任务分解完全一致。当n == 1时,只有一个盘子,简单任务,直接移盘。如果n > 1,则分解为两个 n - 1 的汉诺塔子问题,以及一个简单移盘任务。子问题的求解以函数递归调用来解决。

上述代码的执行结果如下:

Steps count: 31
The first 3 steps are: ['A --> C', 'A --> B', 'C --> B']

上述结果表明,5盘汉诺塔问题共需要31次移盘。movements列表中按顺序存储了全部的移盘动作。

17.1.3 计算复杂性

使用前小节中的程序,作者尝试计算了n = 5 … 12汉诺塔问题的移盘过程,得到下述移盘次数。

89c8716687b6f0c1934a3d1f5a2be765.png

看起来,似乎n个盘的汉诺塔问题的移盘次数为2n-1。事实上,对移盘次数的数学分析可以证明这个结论。n盘的汉诺塔求解可以拆分成两个n-1盘的汉诺塔求解再加上1次简单移盘。如果用T(n)来表示n盘汉诺塔的移盘次数的话,函数T(n)可使用下述递归定义。

c9ba5adaf00977d8bbdc071dd32b24ce.png

我们试着把递归函数消解成非递归函数。

271666dc3c19a54e8c1745939004a1e7.png

令t = n - 1,有:

c861f72bde359a4e6cf59e7eff378010.png

故n盘汉诺塔共需移盘2n-1次。那么,如果梵天规定的是64个金盘的话,总移动次数则为264-1 = 18446744073709551615。如果婆罗门僧侣是个熟练工,1秒挪一个盘,那么1小时可以移3600个盘,1年可移3600 x 24 x 365 = 31536000个盘(忽略闰年误差)。那么,解64盘汉诺塔问题共需要(264-1)/31536000年,即大约5949亿年。看起来,按照当前的人类知识,印度的古老智慧好像高估了地球的预期寿命。

读者不要去尝试计算hanoi(64,’A’,’B’,’C’),显然,在你有限的人生里,是无法完成这件接近“无限”的大事的。而且,因为递归所导致的内存消耗,你有限的计算机内存也排除了这种可能性。

作者是无神论者,上述探讨基于严谨的数学,作者不相信任何人格化的“上帝 ”。

本书同名免费MOOC《Python编程基础及应用》在哔哩哔哩(B站)热播,点击加入,作者带着你学。

Python编程基础及应用 重庆大学 高等教育出版社,作者亲授_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
a427935fb78c9a6ffcb3959e65b31305.png

310525fac5b7c947678451a906a28cdc.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/502226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

reactor模型_Reactor模式以及Netty中的应用

思维导图一、Reactor模式介绍本文主要参考Doug Lea(大神)的《Scalable IO in Java》中讲述的Reactor模式。

sa是什么岗位_服务顾问SA在维修企业扮演的重要角色

前言:SA在维修企业中扮演什么样的角色,这就是我们今天的话题。作者 | 李连俊来源 | 汽车服务世界(ID:asworld168)客户的群体很多,不同的客户群体消费的能力不一样,SA简称【服务顾问】。SA要对客户的消费能力进行评估&a…

java cxf 不使用springmvc_使用cfx与springMVC集成发布与调用webservice

客户端调用代码 Client.java package com.quickmap.common;import javax.xml.namespace.QName;import javax.xml.ws.Service;import javax.xml.ws.soap.SOAPBinding;public final class Client {private static final QName SERVICE_NAME new QName("http://common.quickm…

基于hadoop的商品推荐系统_【论文笔记】基于矩阵分解的推荐系统

本文是对经典论文的阅读笔记,大部分为论文的中文翻译内容(笔者英语水平也就六级飘过的水准,不喜勿喷)论文标题:Matrix factorization techniques for recommender systems随着Netflix竞赛的结果所示,矩阵分…

php fpm在哪配置,php7的php-fpm.conf文件在哪里

php7下的php-fpm.conf文件一般是在php的安装目录下的etc目录中,文件路径为/usr/local/php-fpm/etc/php-fpm.conf。php-fpm.conf是php-fpm进程管理器的配置文件。php-fpm.conf是php-fpm进程管理器的配置文件。文件路径:/usr/local/php-fpm/etc/php-fpm.co…

aba会导致问题_肌肤缺水会导致哪些问题呢?我们又该怎么判断呢?

一.如何判断皮肤是否缺水?01.脸部肌肤粗糙,有紧绷感很多人在日常中都会用到洗面奶吧,在用过洗面奶之后如果发现肌肤变得粗糙,有紧绷感,那么说明你的肌肤就需要补水了。02.化妆之后浮粉、起皮如果给肌肤补足充足的水分&…

spring更新后 外层事务查不到_再深一点:面试工作两不误,源码级理解Spring事务...

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。Spring有5种隔离级别,7种传播行为。这是面试常问的内容,也是代码中经常碰到的知识点。这些知识枯燥而且乏味,其中有些非常的绕…

箭头函数的this指向谁_高阶函数

NodeJS 系列文章,本篇是第一篇,首先,预计将后续高频使用逻辑串一遍,依次是高阶函数,promise以及事件机制。本篇主要是高阶函数。call、bind、applycall、apply 都是改变 this 指向,区别是接受参数的方式不一…

php怎么加编码,php怎么设置编码格式

php设置编码格式的方法:首先在php脚本中添加【header(“Content-Type: text/html; charsetutf-8")】;然后在静态页面设置编码;最后保证所有文件的编码相同即可。如果要使用gb2312编码,那么php要输出头:(推荐教程&…

java 中文 音序,java 中文字符串数组按照音序排列

java 中文字符串数组按照音序排列复制代码 代码如下:public class SortComparator implements Comparator{public int compare(Object o1,Object o2) {try{byte[] buf1 ((String) o1).getBytes("unicode");byte[] buf2 ((String) o2).getBytes("unicode"…

动感灯箱制作流程培训_广告立体灯箱的特点有哪些?

随着广告业的发展,灯箱广告行业也在突飞猛进。在灯箱广告屏的设计与制作中,为了追求真实感和艺术性,采用彩印或摄影喷绘;也有人用特种纸、塑料板(膜)、灯箱布等进行丝网印刷制作灯箱图片,并根据成本和耐候性要求选择制作方法和灯箱…

supervisor 重启_supervisor_twiddler的使用

点击上方蓝字关注【 北邮郭大宝 】Supervisor可以很好的实现Python的进程管理,但是新增进程时需要配置文件,对于需要动态创建进程的场景不是很友好,supervisor_twiddler插件可以帮助实现上述功能。本文就supervisor_twiddler的使用做简单的de…

matlab的词云,Word Cloud (词云) - JavaScript

在上一篇中已经分享了用 Python 创建词云了。接下来继续总结其他创建词云的方法。&带道术用量确示常构端析以要效开的用,近不gt;> Create Word Cloud via JavaScrip要圈器是天的年编功小还久概据含直这请框结业未商屏页屏随会维气大机域页效实一应控高标tJav…

unique函数_unique函数使用场景(一)

unique函数使用场景(一)前情提示:Microsoft 365(就是原来的office 365)已经推出有一段时间了,去年年审就在项目上使用365更新的一系列动态函数来提高审计效率(大胆一点,就是更好的偷懒)。讲解动态函数的文章不多,且365普及度低&am…

c++gdal如何在大图像中截取小图像并获取其图像信息_【图像处理】OpenCV系列十 --- 边缘检测之Canny算子...

上一篇我们学习了图像处理形态学相关知识点,相信大家学习之后已经对形态学有了足够的理解了,那么接下来,我们一起来学习一下图像处理中的边缘检测吧!我们将会重点学习边缘检测各种算子和滤波器 --- Canny算子,Sobel算子,Laplace算…

笔记本屏幕30hz_你真的了解笔记本电池和电源适配器吗?

很多笔记本硬件配置相似,但续航或性能却相差一大截。实际上,笔记本的续航能力在很大程度上取决于电池;而实际性能,则还会受到电源适配器功率的影响。想认识这两个硬件,就需要从它们的基本参数谈起。笔记本电池笔记本的…

java 俄文,俄文字体在word里面是什么

在Word里输入俄语字母,一打字字体就变成宋体了,俄语字母间间距...我不知道你这个俄语输入法补丁的字库用的是什么,如果是汉字库里好像就没办法调了,试一下把字体改成西文的Times New Roman、Arial等字体看有没有变化,如果没有,那就…

excel公式不自动计算_【纯干货】值得收藏的Excel日期计算公式!

点击上面“零壹快学”关注我们小伙伴们好,今天零壹学长给大家整理了一些常用的日期计算公式,赶紧往下看吧!01根据身份证号计算出生年月--TEXT(MID(A2,7,8),"0-00-00")02根据身份证号提取性别IF(MOD(MID(A2,15,3),2),"男"…

项目开发流程_绿维文旅:旅游项目开发模式与流程

一、旅游项目开发模式旅游综合开发是立足旅游项目自有资源基础,以旅游产业为主导,以市场为导向,以资本为驱动,以资源整合为核心,通过集中土地、资本、技术、交通、劳动力等生产要素,推进土地开发、交通建设…

Java继承_java练习本(20190617)

公众号回复“1”,小刀拉你进学习交流群哟,妈妈再也不担心我学习没人陪伴啦~昨日翻译昨日翻译“The journey of a thousand miles begins with one step.”——Lao Tzu“千里之行始于足下。”——老子今日名言“Imagination was given to man to compensa…