递归---Hanoi塔问题
http://shmilyaw-hotmail-com.iteye.com/blog/2077098
简介
关于Hanoi塔问题的分析,在网上的文章都写烂了。之所以打算写这篇文章,更多的是针对这个问题相关的各种数学思路和代码实现过程做一个总结。它虽然是一个看似简单的问题,后面引申出来的问题推导方法和思路还是比较丰富的。
问题描述
这个问题起源于一个类似传说故事,在Hanoi这个地方有一个寺庙,这里有3根柱子和64个大小不同的金碟子。每个碟子有一个孔可以穿过。所有的碟子都放在第一个柱子上,而且按照从上到下碟子的大小依次增大的顺序摆设。如下图:
现在,假定寺庙里的僧侣要移动这些碟子,将它们从最左边移动到最右边的柱子上。不过移动的规则如下:
1. 每次只能从一个柱子的最上面移动一个碟子到另外一个柱子上。
2. 不能将大碟子放到小碟子的上面。
按照前面这个规则,我们该怎么去移动这些碟子呢?假定单位时间内可以移动一片碟子,那么最终移动这些碟子到目的柱子需要多长的时间呢?
问题分析
在分析这个问题的时候,我们可以先从一些简单的场景来看怎么来移动碟子保证可以达到目的。假定我们有3个碟子,那么移动它们的过程如下图:
我们假定柱子从左到右分别为a, b, c。从前面移动碟子的步骤可以看到,我们要将a上面的两个碟子先移动到中间的b柱子作为过渡,然后再将最下面的柱子移动到目的c柱子,然后再将上面的两个碟子移过来。在将最下面的碟子移动到c之前,首先的步骤1, 2, 3是将上面的碟子移动到柱子b。而将最下面碟子移动后,上面的两个碟子又要移动一遍,不过是从b移动到c,只是借助的柱子不一样。
所以,从上面的过程,我们可以看到一个可以递归解决问题的思路,如下图:
如图所示,首先我们针对有n个碟子的柱子a,将n-1个碟子移动到柱子b。假定这个问题为S(n)表示移动的步数,则上面的问题是S(n)的一个子问题S(n-1)。这一步对应步骤1。然后将最下面的碟子移动到柱子c,最后再将n-1个碟子移动到c。后面这一步也相当于S(n)的子问题S(n-1)。对应步骤3.它和前面第一步移动n-1个碟子唯一不同的地方在于第一步是借助c将n-1个碟子从a移动到b,而最后这一步是借助a将n-1个碟子从b移动到c。除了借助的柱子和目的柱子不一样,其他的都是一样的。
这样我们就可以很容易得到一个这样的推导关系:
S(n) = 2S(n - 1) +1
再考虑一种初始的情况,假定只有一个碟子需要移动,我们直接将碟子从a移动到c,那么需要的步骤是1步。因此可以说S(1) = 1。
进一步推导
有了前面的归纳关系,我们可以很容易得到如下的一组推导结果:
S(1) = 1
S(2) = 2 x S(1) + 1 = 2 + 1 = 3
S(3) = 2 x S(2) + 1 = 2 x 3 + 1 = 7
S(4) = 2 x S(3) +1 = 2 x 7 + 1 = 15
从这些得出来的结果里,似乎还看不到多少有规律的地方。不过我们可以采取一种根据递推原则代换的方式来尝试发现规律。前面的推导关系里有S(n) = 2 x S(n - 1) +1,那么我们将有如下的推导:
这里,我们发现什么规律没?原来,这里似乎符合如下的一个等式:
当我们最终一路递推到T1的时候,它将满足如下的形式:
这似乎是我们所求得的结果了。当然,这种推导也有可能会出错。最好的情况是我们还需要验证一下它。验证的方法可以考虑用数学归纳法。因为过程比较简单,这里就不再赘述了。最终可以验证出来结果是满足以上等式的。从前面的推导我们可以看出,最终要实现将64个碟子移动到目的柱子,需要的时间是2的64次方这个量级的。在一定程度上,用计算机的内置数据类型都没法表示这个数值。
#include <iostream>using namespace std;//Hanoi塔问题,借助c,将n个盘子从a移到b
void hanoi(int n,char a,char b,char c)
{if(n>0){hanoi(n-1,a,c,b);//借助b,将n-1个盘子从a移到c上cout<<"将"<<a<<"中最大的盘子从"<<a<<"移到"<<b<<endl;hanoi(n-1,c,b,a);//借助a,将n-1个盘子从c移到b上}
}
int main()
{char a='A',b='B',c='C';hanoi(3,a,b,c);return 0;
}
#include <iostream>
#include <stdio.h>
using namespace std;//第一个塔为初始塔,中间的塔为借用塔,最后一个塔为目标塔
int i=1;//记录步数
void move(int n,char from,char to) //将编号为n的盘子由from移动到to
{printf("第%d步:将%d号盘子%c---->%c\n",i++,n,from,to);
}
void hanoi(int n,char from,char denpend_on,char to)
//将n个盘子由初始塔移动到目标塔(利用借用塔)
{if (n==1)move(1,from,to);//只有一个盘子是直接将初塔上的盘子移动到目的地else{hanoi(n-1,from,to,denpend_on);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上move(n,from,to); //将剩下的一个盘子移动到目的塔上hanoi(n-1,denpend_on,from,to);//最后将借用塔上的n-1个盘子移动到目的塔上}
}
int main()
{printf("请输入盘子的个数:\n");int n;scanf("%d",&n);char x='A',y='B',z='C';printf("盘子移动情况如下:\n");hanoi(n,x,y,z);//A--->Creturn 0;
}
移动步骤:
假设a,b,c排成一个三角形,a--->b--->c--->a构成顺时针循环,移动圆盘过程中,若奇数次移动,则将最小的圆盘移动到顺时针方向的下一塔,若是偶数次移动,则保持最小的圆盘不动,在其他两个塔之间将较小的圆盘移动到另一个上。
递归---Hanoi塔问题相关推荐
- 递归-Hanoi塔问题
设a,b,c是3个塔座.开始时,在塔座a上有一叠共n个圆盘,这些圆盘自下而上,由大到小地叠在一起.各圆盘从小到大 编号为1,2, -,n,现要求将塔座a上的这一叠圆盘移到塔座b 上,并仍按同样顺序叠置 ...
- c语言递归求塔移动次数,【C语言】Hanoi(汉诺)塔问题,求移动盘子的步骤(递归法)...
所有的循环算法都可以用递归实现,反之不成立,这足以证明递归的重要性! Hanoi(汉诺)塔问题.古代有一个焚塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在上,小的在下,有一 ...
- 基础算法:Hanoi塔(递归)
Hanoi塔 "递归算法离不开递推方程的求解." 这里Hanoi塔有三个柱子,A\B\C.上面放着五个盘子,要将A柱的盘子全部移到C柱上: 其中规则: 1.小圆盘必须在大圆盘上面. ...
- C++ Hanoi塔学习笔记(递归与非递归实现)
自己学习理解的笔记,欢迎补充. 1.Hanoi塔问题的递归解法 void Hanoi(int n, char a, char b, char c) {if (n == 1) {cout << ...
- C语言中Hanoi塔问题的递归实现
Hanoi塔问题是一个古典的数学问题,也是一个用递归方法解题的典型例题.其中问题为:古代有一个梵塔,塔内有三个座A,B,C.开始时A座上有64个盘子,盘子的大小不等,大的在下,小的在上.有一个老和尚想 ...
- 双色Hanoi塔问题-递归
双色Hanoi塔问题-递归 思想:1-将n-1个圆盘从A移动到C,B为辅助 2-将第n个圆盘从A移动到B,C为辅助 3-将n-1个圆盘从C移动到B,A为辅助 方式1:键盘输入,控制台输出. impor ...
- Hanoi塔(分治法的应用)
1.分治法 分治法的设计思想是将一个难以直接解决的大问题分解成一些规模较小的相同问题,以便各个击破,分而治之. 一般来说,分治算法在每一层递归上都有3个步骤: (1)分解:将问题分解成一系列子问题. ...
- Hanoi塔(汉诺塔/梵天塔)问题
Hanoi塔 汉诺塔(梵天塔/Hanoi)问题是计算机中比较典型的一个递归问题.废话不多说了,直接上代码. Python3.5代码 """重温本科学习过之书籍:计算机科学 ...
- 小知识系列(3):Hanoi塔(汉诺塔,河内塔)
同样,借此来强化学习,但是说实话我写这个感觉很玄.Hanoi塔是昨天刚学到的东西,想了很久,感觉还是没有悟透,可能学到更多新东西,或产生了新的想法,或突然悟到了什么,届时会再做修改. 看了很多关于Ha ...
最新文章
- Linux修改文件权限为777
- FrostSulliven最新发布引领全球增长的60大技术
- python3连接mysql_第七篇:Python3连接MySQL
- 初中计算机知识点 考题,初中信息技术考题规律及趋势_教师资格面试初中信息技术...
- ML 自学者周刊:第 3 期
- 神经网络 测试集loss不下降_【NLP高频面试题】神经网络及其优化
- 一条查询SQL 语句是如何执行的?
- 算法6-1:哈希函数
- 笔记:Java虚拟机运行时数据区
- kubernetes日志采集与解析
- 计算机与人脑_人脑和计算机相比,谁具有更强的能力?听完科学家的解释恍然大悟...
- 菜鸟学习笔记:Java提升篇12(Java动态性2——动态编译、javassist字节码操作)
- ~~高精度除以低精度
- python核心编程第二版第六章答案
- RS485接收数据后发送乱码
- outlook服务器邮件满了怎么办,Outlook邮箱不能接收邮件提示邮件箱已满怎么办?
- 拒做背锅侠!如何利用网站性能优化驱动产品体验提升
- Java坑人面试题系列: 包装类(中级难度)
- 2D转换+动画+3D转换
- 2011深信服校园招聘笔试面试
热门文章
- Win7下安装Ubuntu16.04以及Ubuntu配置Android环境
- matlab中资源管理无法打开,安装资源的解决办法
- windows 7重装系统(简单实用)
- 【详解】KMP算法——多图,多例子(c语言)
- 一个简单的vue下拉模糊查询
- 8.0服务器维护时间,08月13日服务器维护更新公告
- 人口普查数据集独热编码转换
- Push rejected: Push xxxx to origin/xxxx was rejected by remote问题
- (11/∞)每日一练{1.将一张100元钞票换成等值的10元,5元,2元和1元的小钞,每次换成40张小钞,要求每一种小钞都要有,编程求出所有可能的换法总数输出并输出各换法的组合。}
- 基于Python实现校园网自动登录