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,一经查实,立即删除!

相关文章

java算程序运行时间_关于计算Java程序运行时间

第一种是以毫秒为单位计算的。Java代码//伪代码long startTimeSystem.currentTimeMillis(); //获取开始时间doSomeThing(); //测试的代码段long endTimeSystem.currentTimeMillis(); //获取结束时间System.out.println("程序运行时间: "(end-start)&qu…

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

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

Java文件路径及文件名乱码_javaweb文件下载及文件名中文乱码处理

版权声明:yanghaha的原创博客 https://blog.csdn.net/qq_44758435/article/details/90636619文件下载需要先导入两个jar包commons-fileupload-1.3.1.jarcommons-io-2.4.jarString fileName request.getParameter("fileName");//下载文件,需要…

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

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

java报错symbol_为何此处会出现找不到symbol的错误呢?

使用this不是引用创建的对象么?import java.util.Comparator;import java.lang.Comparable;public class Point implements Comparable {int x, y;public final Comparator SLOPE_ORDER new ByOrder();private class ByOrder implements Comparator {public int co…

python pdf转txt保留全部信息_Python 将pdf转换成txt(不处理图片)

上一篇文章中已经介绍了简单的python爬网页下载文档,但下载后的文档多为doc或pdf,对于数据处理仍然有很多限制,所以将doc/pdf转换成txt显得尤为重要。查找了很多资料,在linux下要将doc转换成txt确实有难度,…

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…

python表单处理_python flask 表单处理Flask-WTF

涉及到的插件和包有Flask-WTF,WTForms。内容有表单的创建使用流程,一些最佳实践,还有在页面显示提示消息的简单方式,配合Flask内置的 flash()。Flask的requset对象包含了client端发送过来的所有请求,在request.form中就有POST方法…

电脑环境变量设置 java_如何设置自己电脑的系统环境变量?

Windows下JAVA用到的环境变量主要有3个,JAVA_HOME、CLASSPATH、PATH。下面逐个分析。JAVA_HOME指向的是JDK的安装路径,如x:\JDK_1。4。2,在这路径下你应该能够找到bin、lib等目录。值得一提的是,JDK 的安装路径可以选择任意磁盘目…

用python实现打开虚拟机_如何使用python从虚拟机读取文件

我使用oraclevirtualbox在我的系统上运行一个虚拟机,我要完成的是从物理系统读取虚拟机上的文件。我正在使用virtualbox api(pyvbox)与virtualbox进行接口。这是我第一次使用virtualbox api。在更新>>> import virtualbox>>> vbox virtualbox.Vi…

java 调用 mahout_java – 运行Mahout本地获取MahoutDriver的ClassNotFoundException

我试图在Windows 8机器上本地运行Mahout(没有Hadoop).我意识到这不是最佳设置,但这就是我必须使用的.当我尝试运行bin / mahout时,我收到以下错误:$bin/mahoutMAHOUT_LOCAL is set, so we dont add HADOOP_CONF_DIR to classpath.no HADOOP_HOME set, running local…

java写hive自定义函数_hive自定义函数的实现和执行

1. 先建个maven工程,创建Java类,将你要实现的内容写进类的方法里,例如public class StringExt extends UDF{public String evaluate(String pnb){return "Hello " pnb;}}这个类的实现很简单,继承了org.apache.hadoop.h…

python创建文件夹用什么函数_Python——os.mkdir()在指定路径下创建文件夹 + 路径的连接理解...

Python——os.mkdir()在指定路径下创建文件夹 路径的连接理解发布时间:2018-11-16 17:08,浏览次数:512, 标签:Pythonosmkdir引子: 我在用路径连接函数 os.path.join() 时发现,其连接的各级目录必须首先存在&#xff0…

基于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…

python 生成pdf页面大小_(Python)更改使用xtopd生成的PDF文件的页面大小和格式

我想用Python转换xlsx。我使用tablib和xtopdf模块构建了一个结构良好的表。工作出色!不幸的是,内容不适合一个pdf页面。所以我想把页面大小和格式改成水平A3。但我不知道这怎么可能。我的代码:import randomimport tablibfrom openpyxl impor…

php数组合并字段,PHP数组按要求合并

数组一:[0] > Array([rid] > 1[hf_rid] > 0[aid] > 1[uid] > 1[content] > 我肯定第一名[re_time] > 2017-10-10 10:59[nickname] > 就是这么帅)[1] > Array([rid] > 2[hf_rid] > 0[aid] > 1[uid] > 1[content] > 马蛋,中枪了[re_ti…

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

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

php编写用户登录页面,js+php实现静态页面实时调用用户登陆状态的方法

这篇文章主要介绍了jsphp实现静态页面实时调用用户登陆状态的方法,采用在静态页面中使用js调用php页面从而实现用户登录状态的实时调用功能,需要的朋友可以参考下本文实例讲述了jsphp实现静态页面实时调用用户登陆状态的方法。分享给大家供大家参考。具体分析如下:在…

python调试和测试有什么区别和联系_软件测试和测试开发到底有什么区别跟联系?...

对于没有进入IT领域的同学而言,软件测试并不陌生,但如果听到测试开发,他们一定会感到十分困惑,这究竟是测试还是开发呢?按照字面意思理解,大家或许会觉得测试开发是指既能开发产品又能测试产品的“技术王者…