汉诺塔(梵塔)问题递归解决
汉诺塔(梵塔)问题描述:来自于百度百科
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
输入:输入汉诺塔(梵塔)的铜板个数
输出:要求输出每一步移动的操作,并输出最终步数
示例如下:
简要分析:
对于梵塔问题,递归解决是比较容易想到的。我们以三个铜板的梵塔问题为例来进行讲解。
我们要将A柱上的三个铜板移到C上,并且不破坏规则(小的铜板不能在大的铜板下)。在保证规则不被破坏的前提下,我们有这样一个策略来移动铜板: 每次都将最大的铜板移到C上。
为了达到上面的策略,我们要有一下两个步骤:
- 将除去最大的铜板的所有铜板(1、2号铜板)移到B上
- 将最大的铜板(3号铜板)移到C上(达到目的)
在完成以上两步后,我们实现了将现在最大的铜板(3号铜板)移到目标C上。下一步需要将次小的铜板(2号铜板)从当前的位置B上移动到C上。这相当于重复了上面的步骤,只不过此时要移动的铜板是次小的铜板(2号铜板),移动的起始位置也从A换到了B,但是目标位置不变,依然为C。
如此执行下去,最终我们将所有铜板从A移动到C,而且我们每次移动的都是依次变小的铜板,符合规则。
那么现在就只剩下一个问题: 上述步骤中的步骤一将除去最大的铜板外的所有铜板(1、2号铜板)移到B上如何实现呢? 我们来分析初始问题与当前问题:
- 初始的问题: 将所有的铜板(1、2、3)从A移动到C(不破坏规则)
- 现在的问题: 将除去最大的铜板(1、2)从A移动到B(不破坏规则)
很容易发现,这与初始问题描述一样,只不过更换了铜板数量和目标位置。相当于减小了问题规模,我们依然可以采取上述两个步骤的策略来解决子问题,而子问题又有自己的子问题…
这一特性十分适合我们采用递归的方式来解决这一问题。
也许你还不太清除如何代码实现,但递归问题解决这一问题的思想大概如此(我们语言能力有限,可能你对于思想也不太清除,下面给一份C++编辑的代码,帮助你理解汉诺塔问题)。
代码如下:
#include<iostream>
using namespace std;
/*我们分别以 -1(A) , 0(B) , 1(C) 代表梵塔问题的三个柱.起始时默认所有的盘均在 -1 号柱上.当然我们在输出时依然按照A、B、C来表示铜板号,这样更加直观。
*/
void Just_do_it(int num,int goal,int position); //含义: 将1-num的所有铜板从position移到goal
void Move(int moveNum,int goal,int position); //含义: 将moveNum号的铜板从position移到goal
int GetGoal(int goal,int position); //含义: 根据目标(goal)和当前位置(position)获取接下来要去哪里
char* GetPrint(int n); //含义: 格式化输出
int step = 0; //步数
int main()
{int panNum; //铜板的数量,默认铜板的编号从1到panNum。 且编号越大,铜板的大小也越大。cout<<"请输入铜板的数量: "; cin>>panNum;Just_do_it(panNum,1,-1); //将所有的铜板从-1柱移到1号柱。cout<<"step: "<<step<<endl;return 0;
}void Just_do_it(int num,int goal,int position)
{for(int i=num; i>0; i--){Move(i,goal,position);if(goal + position == 0){ position = 0; }else if(goal + position == -1){ position = 1 ;}else{ position = -1; }}
}void Move(int moveNum,int goal,int position)
{if(moveNum == 1){step++;cout<<"move 1 from "<<GetPrint(position)<<" to "<<GetPrint(goal)<<endl;}else{Just_do_it(moveNum-1,GetGoal(goal,position),position);step++;cout<<"move "<<moveNum<<" from "<<GetPrint(position)<<" to "<<GetPrint(goal)<<endl;}
}int GetGoal(int goal,int position)
{if(goal + position == 0){ return 0; }else if(goal + position == -1) { return 1;}else { return -1; }return -9; //随便返回一个,因为走不到这一步
}char* GetPrint(int n){if( n == -1){ return "A"; }else if( n == 0) { return "B"; }else { return "C"; }return "error!"; //随便返回一个,因为走不到这一步
}
汉诺塔(梵塔)问题递归解决相关推荐
- 2016年圣诞节巨献:C#汉诺塔河内塔游戏(动画、圣诞节音效)源码及安装包
终于把VS的的打包搞定了,高兴啊! 圣诞节巨献:C#汉诺塔河内塔游戏(动画效果.圣诞节音效).在平庸而又乏味的生活中,来一把紧张而刺激的汉诺塔游戏,生活,就是这么美好.游戏代码可以在博主的资源页下载! ...
- c语言递归汉诺塔次数,c语言递归解决汉诺塔参数变化的疑惑
c语言递归解决汉诺塔参数变化的疑惑 答案:3 信息版本:手机版 解决时间 2020-04-05 14:20 已解决 2020-04-05 10:49 #include void main() {vo ...
- 利用递归、迭代解决斐波那契数列问题与汉诺塔难题
有人说,"普通程序员使用迭代,天才程序员使用递归",真是这样吗? 1.浅谈递归与迭代 <1>递归的基本概念: 程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个 ...
- C++非递归解决汉诺塔问题
汉诺塔问题简述:将塔A上的n个大小不一的盘子借由塔B全部移动到塔C上,且在过程中不能将大盘子放在小盘子上. 目录 1.算法: 2.具体效果: 3.SeqStack.c ...
- 2.2基本算法之递归和自调用函数_用栈算法递归解决汉诺塔问题
今天博主收一下线性表的尾,最近我们要学习的内容是栈和队列板块,栈和队列板块分为两讲,第一讲也就是今天我们主要学习栈的相关知识,包括栈的定义.栈的顺序表示及实现,栈的链式表示,栈的应用举例,以及栈递归实 ...
- c语言递归解决汉诺塔问题
c语言递归解决汉诺塔问题 参考文章: (1)c语言递归解决汉诺塔问题 (2)https://www.cnblogs.com/didiaoxiaoguai/p/6686407.html 备忘一下.
- 由递推关系式用差分方程的方法得到通项公式实现求斐波那契数列的第n项;迭代、递归、栈、差分方程之间的本质联系以及由推广的迭代法解决“变态青蛙跳台阶”问题;汉诺塔问题的数字特征以及用递归解决的原理推导。
最近几天在研究算法中一个比较基础且突出的问题,就是关于"递推关系式.递归.迭代.序列前k项和"之间的区别与联系. 一.斐波那契数列与差分方程 首先我们考察一个经典的算法,求斐波那契 ...
- 用函数递归的方法解决汉诺塔问题
函数递归算法的运用有一个经典例题,那就是汉诺塔问题,接下来就让我们一起来看看如何用函数递归来解决汉诺塔问题叭! 汉诺塔问题的起源: 汉诺塔(又称河内塔)问题是印度的一个古老的传说.开天辟地的神勃拉玛在 ...
- ICS计算系统概论LC3汇编实验Lab5—中断、递归解决汉诺塔问题
Lab Purpose 完成用户程序的编写. 编写下面描述的键盘中断服务例程. condition: 用户程序: 汉诺塔的参数,记录为N,将用xFFFF初始化并存储在X3FFF内存中. 您的用户程序从 ...
最新文章
- 台积电和三星成半导体代工厂恶战主角 受谁影响?
- GDCM:读取gdcm::DataSetHelper的测试程序
- Activity容器控件
- iOS 7开源项目干货集合
- 使用从mysql中取数据
- 一张正面人脸照片,3D真人头像毫秒级重建。
- UNIX环境高级编程习题——第三章
- postSQL安装和GIS数据导入
- sql中多表连接查询——自连接
- opencv3.0 截取任意形状封闭图形
- R语言hist作直方图
- 扫雷外挂的设计与实现
- Glide加载圆形图片带白色边框
- 继承 封装 多态 (基础)描述性理解
- LeetCode-只出现一次的数字-哈希表-异或-py
- \t\t无锡联通宽带最新覆盖小区名单?
- TMDS编解码原理与实现
- Landsat5数据下载中国地区1988年
- 怎么样才能在CODELITE中输出中文呢!!!
- 40%带宽成本节约!京东云视频云正式支持AV1编码