汉诺塔问题(分治+源码+动画演示)

汉诺塔问题源自印度一个古老的传说,印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱,其中的一根柱子上按照从小到大的顺序摞着 64 个黄金圆盘。梵天命令一个叫婆罗门的门徒将所有的圆盘移动到另一个柱子上,移动过程中必须遵守以下规则:

每次只能移动柱子最顶端的一个圆盘;

每个柱子上,小圆盘永远要位于大圆盘之上;

图 1 给您展示了包含 3 个圆盘的汉诺塔问题:

图 1 汉诺塔问题

一根柱子上摞着 3 个不同大小的圆盘,那么在不违反规则的前提下,如何将它们移动到另一个柱子上呢?图 2 给大家提供了一种实现方案:

图 2 汉诺塔问题的解决方案

汉诺塔问题中,3 个圆盘至少需要移动 7 次,移动 n 的圆盘至少需要操作 2n-1 次。

在汉诺塔问题中,当圆盘个数不大于 3 时,多数人都可以轻松想到移动方案,随着圆盘数量的增多,汉诺塔问题会越来越难。也就是说,圆盘的个数直接决定了汉诺塔问题的难度,解决这样的问题可以尝试用分治算法,将移动多个圆盘的问题分解成多个移动少量圆盘的小问题,这些小问题很容易解决,从而可以找到整个问题的解决方案。

分治算法解决汉诺塔问题

为了方便讲解,我们将 3 个柱子分别命名为起始柱、目标柱和辅助柱。实际上,解决汉诺塔问题是有规律可循的:

  1. 当起始柱上只有 1 个圆盘时,我们可以很轻易地将它移动到目标柱上;

  2. 当起始柱上有 2 个圆盘时,移动过程如下图所示:

图 3 移动两个圆盘

移动过程是:先将起始柱上的 1 个圆盘移动到辅助柱上,然后将起始柱上遗留的圆盘移动到目标柱上,最后将辅助柱上的圆盘移动到目标柱上。

  1. 当起始柱上有 3 个圆盘时,移动过程如图 2 所示,仔细观察会发现,移动过程和 2 个圆盘的情况类似:先将起始柱上的 2 个圆盘移动到辅助柱上,然后将起始柱上遗留的圆盘移动到目标柱上,最后将辅助柱上的圆盘移动到目标柱上。

通过分析以上 3 种情况的移动思路,可以总结出一个规律:对于 n 个圆盘的汉诺塔问题,移动圆盘的过程是:

将起始柱上的 n-1 个圆盘移动到辅助柱上;

将起始柱上遗留的 1 个圆盘移动到目标柱上;

将辅助柱上的所有圆盘移动到目标柱上。

由此,n 个圆盘的汉诺塔问题就简化成了 n-1 个圆盘的汉诺塔问题。按照同样的思路,n-1 个圆盘的汉诺塔问题还可以继续简化,直至简化为移动 3 个甚至更少圆盘的汉诺塔问题。

如下为分治算法解决汉诺塔问题的伪代码:

// num 表示移动圆盘的数量,source、target、auxiliary 分别表示起始柱、目标柱和辅助柱 hanoi(num ,
source , target , auxiliary):
if num == 1: // 如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱
print(从 source 移动到 target)
else:
// 递归调用 hanoi 函数,将 num-1 个圆盘从起始柱移动到辅助柱上,整个过程的实现可以借助目标柱
hanoi(num-1 , source , auxiliary , target)
// 将起始柱上剩余的最后一个大圆盘移动到目标柱上
print(从 source 移动到 target)
// 递归调用 hanoi 函数,将辅助柱上的 num-1 圆盘移动到目标柱上,整个过程的实现可以借助起始柱
hanoi(n-1 , auxiliary , target , source)

汉诺塔问题的代码实现

根据伪代码,我们为大家编写好了相应的 C 语言、Java 以及 Python 程序。

如下是解决汉诺塔问题的 C 语言程序:

#include <stdio.h>
void hanoi(int num, char sou, char tar,char aux) {//统计移动次数static int i = 1;//如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱if (num == 1) {printf("第%d次:从 %c 移动至 %c\n", i, sou, tar);i++;}else {//递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上hanoi(num - 1, sou, aux, tar);//将起始柱上剩余的最后一个大圆盘移动到目标柱上printf("第%d次:从 %c 移动至 %c\n", i, sou, tar);i++;//递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上hanoi(num - 1, aux, tar, sou);}
}
int main()
{//以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示hanoi(3, 'A', 'B', 'C');return 0;
}

如下是解决汉诺塔问题的 Java 程序:

public class Demo {// 统计移动次数public static int i = 1;public static void hanoi(int num, char sou, char tar, char sux) {// 如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱if (num == 1) {System.out.println("第" + i + "次:从" + sou + "移动到" + tar);i++;} else {// 递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上hanoi(num - 1, sou, sux, tar);// 将起始柱上剩余的最后一个大圆盘移动到目标柱上System.out.println("第" + i + "次:从" + sou + "移动到" + tar);i++;// 递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上hanoi(num - 1, sux, tar, sou);}}public static void main(String[] args) {// 以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示hanoi(3, 'A', 'B', 'C');}
}

如下是解决汉诺塔问题的 Python 程序:

#记录移动次数
i = 1
def hanoi(num,sou,tar,aux):global iif num==1:print("第%d次:从 %c 移动至 %c" % (i, sou, tar))i=i+1else:#递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上hanoi(num - 1, sou, aux, tar)#将起始柱上剩余的最后一个大圆盘移动到目标柱上print("第%d次:从 %c 移动至 %c" % (i, sou, tar))i=i+1#递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上hanoi(num - 1, aux, tar, sou)
#以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示
hanoi(3, 'A', 'B', 'C');

以上程序的执行结果均为:

第1次:从 A 移动至 B
第2次:从 A 移动至 C
第3次:从 B 移动至 C
第4次:从 A 移动至 B
第5次:从 C 移动至 A
第6次:从 C 移动至 B
第7次:从 A 移动至 B

汉诺塔问题(分治+源码+动画演示)相关推荐

  1. 汉诺塔游戏规律,让汉诺塔沦为体力劳动!(后附汉诺塔解法Python源码)

    记住这个规律,以后玩汉诺塔基本上就是体力劳动了. 规律: 先小后大,单左双右,循环. 设3个柱子分别是甲,乙,丙,把3根柱子看成一个循环,也就是说,甲的右边是乙,乙的右边是丙,而丙的右边则回到甲,同理 ...

  2. 汉诺塔问题——分治思想

    汉诺塔规则如下: 1.有三根相邻的柱子,标号为x,y,z. 2.x柱子上从下到上按金字塔状叠放着n个不同大小的圆盘. 3.现在把所有盘子一个一个移动到柱子z上,并且每次移动同一根柱子上都不能出现大盘子 ...

  3. 汉诺塔在VC控制台的图形演示

    /** 汉诺塔实验: 1.三个塔 A B C 2.把从A 塔借助 B塔转移到C塔 3.盘子的宽比长为3:7 4.开发环境VC+EasyX插件http://www.easyx.cn 注意事项 目前程序只 ...

  4. python算法设计 - 汉诺塔

    python算法设计源码:https://github.com/MakerChen66/Python3Algorithm 版权声明:原创不易,本文禁止抄袭.转载,侵权必究! 目录 一.汉诺塔 二.源码 ...

  5. html实现汉诺塔小游戏

    文章目录 1.设计来源 汉诺塔由来 1.1 主界面 1.2 游戏规则 1.3 游戏完成界面 2.效果和源码 2.1 动态效果 2.2 源代码 源码下载 作者:xcLeigh 文章地址:https:// ...

  6. 汉诺塔自动解题动画中的iOS开发技巧

    引 前段时间做了一道题,要求实现汉诺塔游戏的自动解题动画: 汉诺塔游戏应该都了解规则: 1.将盘子全部移动到塔C 2.每次只能移动一个圆盘: 3.大盘不能叠在小盘上面. 要求由用户输入盘子的数量,绘制 ...

  7. 汉诺塔实践python_汉诺塔的python 动画演示

    1.简介 古代有一座汉诺塔,塔内有3个座A.B.C,A座上有n个盘子,盘子大小不等,大的在下,小的在上,如图所示.有一个和尚想把这n个盘子从A座移到C座,但每次只能移动一个盘子,并且自移动过程中,3个 ...

  8. 分治算法求解汉诺塔问题

    1.什么是分治算法? 分治算法,字面理解"分而治之",就是把一个复杂的问题分成两个或者更多的相同或者相似的子问题,再把子问题分成更小的子问题...直到最后子问题可以直接简单求解,原 ...

  9. 分治算法——汉诺塔(HanoiTower)

    分治算法--汉诺塔 介绍 分治算法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题···直到最后子 ...

最新文章

  1. 谷歌论文:使用深度强化学习的芯片布局
  2. scala-04For与Function进阶实战、Lazy的使用
  3. 最长有效括按号长度(利用栈解决java语言)
  4. 配置Java_Home,临时环境变量信息
  5. linux0775权限,Linux权限管理
  6. [BZOJ1026] [SCOI2009] windy数 (数位dp)
  7. 阿里云基于NVM的持久化高性能Redis数据库
  8. 使用CName记录的好处(转)
  9. 21.TCP/IP 详解卷1 --- TCP 的超时与重传
  10. Web API 2 入门——使用Web API与ASP.NET Web窗体(谷歌翻译)
  11. Jaunt和Dolby联手,为VR视频带来更带感的全景声场体验
  12. 初识Lazarus和Free Pascal Compiler
  13. gcode 解析入门1-1
  14. 【笔记】EFCore SQLite 拼音汉字互换
  15. 去水印原理_图片去水印|视频去水印
  16. 2014年6月份第4周51Aspx源码发布详情
  17. 注册一个域名需要多少钱_域名注册需要多少钱?注册一个域名一般要多少钱?贵吗?...
  18. ipad和android平板应用,排名前100的iPad应用中只有一半支持Android平板
  19. DFD图练习题(信用卡管理系统CCMS)
  20. html td无边框颜色,table的td设置背景颜色后边框框消失

热门文章

  1. 东莞市商业学校计算机平面设计在哪个校区,从长安镇到东莞市石竹路2号东莞市商业学校南城校区东门内...
  2. layer alert时 点击其他地方会关闭
  3. iOS 动画专题(UIView二维形变动画与CAAnimation核心动画)
  4. PHP调用京东联盟开普勒、宙斯API模板
  5. ubuntu20.4服务器搭建ftp并连接(阿里云服务器)
  6. 服务型移动机器人如何实现室内路径全覆盖清扫给你一个清爽干净的家
  7. python面向对象代码_python_面向对象—代码练习
  8. 项目定义软件过程(PDSP:Project's Defined Software Process)1
  9. 对嵌入式FPGA的详解
  10. 【云原生--Kubernetes】Pod重启策略