汉诺塔问题

简介: 汉诺塔问题源自印度古老传说,涉及将一组圆盘从一根柱子移动到另一根,遵循特定规则。文章详细介绍了该问题的背景、解决思路以及如何使用分治算法实现,同时提供了C语言、Java和Python的代码示例。

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

  • 每次只能移动柱子最顶端的一个圆盘;
  • 每个柱子上,小圆盘永远要位于大圆盘之上;


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

 

图1:汉诺塔问题


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


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

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

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

分治算法解决汉诺塔问题

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

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


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


图3:移动两个圆盘


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


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


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

  1. 将起始柱上的 n-1 个圆盘移动到辅助柱上;
  2. 将起始柱上遗留的 1 个圆盘移动到目标柱上;
  3. 将辅助柱上的所有圆盘移动到目标柱上。


由此,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 语言程序:

  1. #include <stdio.h>
  2. void hanoi(int num, char sou, char tar,char aux) {
  3. //统计移动次数
  4. static int i = 1;
  5. //如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱
  6. if (num == 1) {
  7. printf("第%d次:从 %c 移动至 %c\n", i, sou, tar);
  8.        i++;
  9. }
  10. else {
  11. //递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上
  12. hanoi(num - 1, sou, aux, tar);
  13. //将起始柱上剩余的最后一个大圆盘移动到目标柱上
  14. printf("第%d次:从 %c 移动至 %c\n", i, sou, tar);
  15.        i++;
  16. //递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上
  17. hanoi(num - 1, aux, tar, sou);
  18. }
  19. }

  20. int main()
  21. {
  22. //以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示
  23. hanoi(3, 'A', 'B', 'C');
  24. return 0;
  25. }


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

  1. public class Demo {
  2. // 统计移动次数
  3. public static int i = 1;

  4. public static void hanoi(int num, char sou, char tar, char sux) {
  5. // 如果圆盘数量仅有 1 个,则直接从起始柱移动到目标柱
  6. if (num == 1) {
  7.            System.out.println("第" + i + "次:从" + sou + "移动到" + tar);
  8.            i++;
  9. } else {
  10. // 递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上
  11. hanoi(num - 1, sou, sux, tar);
  12. // 将起始柱上剩余的最后一个大圆盘移动到目标柱上
  13.            System.out.println("第" + i + "次:从" + sou + "移动到" + tar);
  14.            i++;
  15. // 递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上
  16. hanoi(num - 1, sux, tar, sou);
  17. }
  18. }

  19. public static void main(String[] args) {
  20. // 以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示
  21. hanoi(3, 'A', 'B', 'C');
  22. }
  23. }


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

纯文本复制

  1. #记录移动次数
  2. i = 1
  3. def hanoi(num,sou,tar,aux):
  4. global i
  5. if num==1:
  6. print("第%d次:从 %c 移动至 %c" % (i, sou, tar))
  7.        i=i+1
  8. else:
  9. #递归调用 hanoi() 函数,将 num-1 个圆盘从起始柱移动到辅助柱上
  10. hanoi(num - 1, sou, aux, tar)
  11. #将起始柱上剩余的最后一个大圆盘移动到目标柱上
  12. print("第%d次:从 %c 移动至 %c" % (i, sou, tar))
  13.        i=i+1
  14. #递归调用 hanoi() 函数,将辅助柱上的 num-1 圆盘移动到目标柱上
  15. hanoi(num - 1, aux, tar, sou)

  16. #以移动 3 个圆盘为例,起始柱、目标柱、辅助柱分别用 A、B、C 表示
  17. 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

相关文章
|
机器学习/深度学习 人工智能 自然语言处理
AI视频大模型Sora新视角:从介绍到商业价值,全面解读优势
Sora是OpenAI于`2024年2月16日`发布的文生视频模型,`能够根据用户输入的提示词、文本指令或静态图像,生成长达一分钟的视频`,其中既能实现多角度镜头的自然切换,还包含复杂的场景和生动的角色表情,且故事的逻辑性和连贯性极佳。
|
安全 C语言
【C语言】如何规避野指针
【C语言】如何规避野指针
220 0
|
人工智能 自然语言处理 数据可视化
中国版“Manus”开源?AiPy:用Python重构AI生产力的通用智能体
AiPy是LLM大模型+Python程序编写+Python程序运行+程序可以控制的一切。
1168 11
|
2月前
|
人工智能 算法
财富管理AI:从产品推荐到资产配置的智能化
银行财富管理AI助手:资产配置+税务优化+退休规划 开源Skill:wealth-management | 资产配置 | 税务优化 | 退休规划 痛点:财富管理的"信息不对称" 银行客户经理面对高净值客户时: 客户问:"我500万怎么配置?" → 经理凭经验推荐 客户问:"怎么合法节税?" → 经理说不清楚 客户问:"我50岁退休够吗?" → 经理算不出来 问题:缺乏量化工具,只能"
|
6月前
|
缓存 NoSQL 关系型数据库
开源扫码点餐系统源码部署实战:服务器与数据库优化方案
本文直击扫码点餐系统落地难点:源码易得,稳定部署难!详解Nginx负载均衡、MySQL索引与读写分离、Redis缓存与分布式锁、雪花算法订单号等十大实战优化方案,助你从架构到代码一步到位,扛住高峰并发。(239字)
|
10月前
|
存储 缓存 Java
重构一个类,JVM竟省下2.9G内存?
通过重构核心类,将 `HashMap<Long, HashSet<String>>` 优化为 `Long2ObjectOpenHashMap<int[]>`,结合数据分布特征与紧凑存储,JVM 堆内存从 3.13GB 降至 211MB,降幅达 94%,验证了高效数据结构在海量场景下的巨大价值。
812 24
重构一个类,JVM竟省下2.9G内存?
|
9月前
|
JavaScript Java 关系型数据库
2026版基于springboot的大学生社团管理系统
本文探讨高校学生社团管理系统的研发背景与意义,分析当前国内研究现状,提出基于Spring Boot、Vue.js、MySQL及B/S架构的技术方案,旨在提升社团管理的信息化、智能化水平,推动校园文化可持续发展。
|
机器人 网络安全 数据安全/隐私保护
autMan奥特曼机器人-对接Docker版本NTQQ详细教程
本文介绍了如何在服务器上搭建NTQQ机器人,通过官方NTQQ对接各框架,实现QQ登录的稳定运行。文章提到了需要准备一台服务器和相应的软件,并详细描述了通过SSH链接服务器、创建文件夹和配置文件、编辑配置文件地址端口、运行容器等步骤。同时,文章还介绍了VNC连接的使用和配置,以及使用watchtower进行NTQQ的更新。文章总结起来就是在服务器上搭建NTQQ机器人,实现QQ登录的稳定性和自动登录功能,同时提供了更新和维护的方法。
1502 3
autMan奥特曼机器人-对接Docker版本NTQQ详细教程
|
机器学习/深度学习 存储 人工智能
深度强化学习实战:训练DQN模型玩超级马里奥兄弟
本文介绍了如何利用深度学习和强化学习技术构建一个能够自主学习并完成《超级马里奥兄弟》游戏的智能系统。通过使用深度Q网络(DQN)架构,智能体在虚拟环境中与游戏进行交互,逐步优化其行为策略。文中详细描述了环境构建、神经网络设计、智能体-环境交互机制等关键步骤,并展示了系统的训练过程和最终表现。该研究不仅展示了强化学习在游戏领域的应用潜力,也为未来的研究提供了宝贵的经验和技术参考。
1000 81
深度强化学习实战:训练DQN模型玩超级马里奥兄弟