一、算法背景

  最早发明这个问题的人是法国数学家爱德华·卢卡斯。传说越南河内某间寺院有三根银棒(A, B, C),上串 64 个金盘。 寺院里的僧侣依照一个古老的预言,以上述规则移动这些盘子;预言说当这些盘子移动完毕,世界就会灭亡。 这个传说叫做梵天寺之塔问题(Tower of Brahma puzzle)。但不知道是卢卡斯自创的这个传说,还是他受他人启发。

A        C        B

二、汉诺塔算法

  有三根杆子A,B,C。A 杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:

  1. 每次只能移动一个圆盘;
  2. 大盘不能叠在小盘上面。

  提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则。

  问:如何移?最少要移动多少次?

  解法的基本思想是递归。假设有 A、B、C 三个塔,A 塔有  块盘,目标是把这些盘全部移到 C 塔。那么先把 A 塔顶部的  块盘移动到 B 塔,再把 A 塔剩下的大盘移到 C,最后把 B 塔的  块盘移到 C。如此递归地使用下去, 就可以求解。

 1     /**
2 * Java递归函数解决河内塔之难题
3 *
4 * @param n 移动物体数量
5 * @param fromRod 原先放的位置
6 * @param toRod 要放去的位置
7 * @param auxRod 中间留空方便转移的位置
8 */
9 private static void towerOfHanoi(int n, char fromRod, char toRod, char auxRod) {
10 count++;
11 if (n == 1) {  // 递归出口
12 System.out.println("Move disk 1 from rod " + fromRod + " to rod " + toRod);
13 return;
14 }
15 towerOfHanoi(n-1, fromRod, auxRod, toRod);
16 System.out.println("Move disk " + n + " from rod " + fromRod + " to rod " + toRod);  // 移动
17 towerOfHanoi(n-1, auxRod, toRod, fromRod);
18 }

  设移动 n 个盘子的汉诺塔问题需要 towerOfHanoi(n) 次移动操作来完成。由展示移动过程算法可知 towerOfHanoi(n) 应是三部分之和。

  (1) 将 n 个盘上面的 n-1 个盘子借助 C 桩从 A 桩移到 B 桩上,需 towerOfHanoi(n-1) 次移动;

  (2) 然后将 A 桩上第 n 个盘子移到 C 桩上(1次);

  (3) 最后,将 B 桩上的 n-1 个盘子借助 A 桩移到 C 桩上,需 towerOfHanoi(n-1)次。

  因而有递归关系: towerOfHanoi(n) = 2 * towerOfHanoi(n-1) + 1,初始条件(递归出口): towerOfHanoi(1) = 1,即 1、3、7、15、31…… 移动次数 count = towerOfHanoi(n) = 2n -1 ,时间复杂度为 O(2n)。

本文源代码:

 1 package algorithm;
2
3 /**
4 * 汉诺塔问题(Tower of Brahma puzzle)
5 *
6 * 最早发明这个问题的人是法国数学家爱德华·卢卡斯。
7 *
8 * 传说越南河内某间寺院有三根银棒,上串 64 个金盘。
9 * 寺院里的僧侣依照一个古老的预言,以上述规则移动这些盘子;预言说当这些盘子移动完毕,世界就会灭亡。
10 * 这个传说叫做梵天寺之塔问题(Tower of Brahma puzzle)。
11 * 但不知道是卢卡斯自创的这个传说,还是他受他人启发。
12 *
13 * 若传说属实,僧侣们需要 2^{64}-1 步才能完成这个任务;
14 * 若他们每秒可完成一个盘子的移动,就需要 5849 亿年才能完成。整个宇宙现在也不过 137 亿年。
15 *
16 * 这个传说有若干变体:寺院换成修道院、僧侣换成修士等等。
17 * 寺院的地点众说纷纭,其中一说是位于越南的河内,所以被命名为“河内塔”。
18 * 另外亦有“金盘是创世时所造”、“僧侣们每天移动一盘”之类的背景设定。
19 */
20 public class TowerOfHanoi {
21 /* 移动次数 */
22 private static int count = 0;
23
24 /**
25 * Java递归函数解决河内塔之难题
26 *
27 * @param n 移动物体数量
28 * @param fromRod 原先放的位置
29 * @param toRod 要放去的位置
30 * @param auxRod 中间留空方便转移的位置
31 */
32 private static void towerOfHanoi(int n, char fromRod, char toRod, char auxRod) {
33 count++;
34 if (n == 1) {
35 System.out.println("Move disk 1 from rod " + fromRod + " to rod " + toRod);
36 return;
37 }
38 towerOfHanoi(n-1, fromRod, auxRod, toRod);
39 System.out.println("Move disk " + n + " from rod " + fromRod + " to rod " + toRod);
40 towerOfHanoi(n-1, auxRod, toRod, fromRod);
41 }
42
43 public static void main(String[] args) {
44 int n = 4;
45 towerOfHanoi(n, 'A', 'C', 'B');
46 /**
47 * 可见移动次数是 (2^n-1), 其时间复杂度O(2^n)。
48 *
49 * 一天24h, 一小时60min, 一分钟60s, 一天有 24*60*60 = 86400(s), 一年平均365天来算,一年有 3153,6000 (s)
50 * 可见要几千亿年才能移动完, 这个算法用于移动大数量小空间的物体肯定是行不通的。
51 *
52 * 这个算法主要考验人的解决问题、逻辑思想, 以及计算推理的能力
53 */
54 System.out.println("移动次数:" + count);
55 }
56 }

算法:汉诺塔问题(Tower of Brahma puzzle)的更多相关文章

  1. 汉诺塔 Hanoi Tower

    电影<猩球崛起>刚开始的时候,年轻的Caesar在玩一种很有意思的游戏,就是汉诺塔...... 汉诺塔源自一个古老的印度传说:在世界的中心贝拿勒斯的圣庙里,一块黄铜板上插着三支宝石针.印度 ...

  2. python算法-汉诺塔问题

    汉诺塔问题   初始状态: 思考:当盘子的个数是3的时候,大家写出移动顺序 移动的步骤: 3个盘子,从a到c 1.前面两个盘子,从a到b 1)把前面一个盘子,从a到c a->c 2)把第二个盘子 ...

  3. C++汉诺塔递归实现

    程序背景: 汉诺塔(Tower of Hanoi)又称河内塔,问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命 ...

  4. 汉诺塔(河内塔)算法 ----C语言递归实现

    汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子, 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘.大梵天命令婆罗门把圆盘从下面开始按大小顺 ...

  5. 汉诺塔算法详解之C++

    汉诺塔: 有三根杆子A,B,C.A杆上有N个(N>1)穿孔圆环,盘的尺寸由下到上依次变小.要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘: 大盘不能叠在小盘上面. 提示:可将圆盘临时置 ...

  6. 汉诺塔算法的递归与非递归的C以及C++源代码

    汉诺塔(又称河内塔)问题其实是印度的一个古老的传说. 开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一 个小, ...

  7. [js - 算法可视化] 汉诺塔(Hanoi)演示程序

    前段时间偶然看到有个日本人很早之前写了js的多种排序程序,使用js+html实现的排序动画,效果非常好. 受此启发,我决定写几个js的算法动画,第一个就用汉诺塔. 演示地址:http://tut.ap ...

  8. C语言之算法初步(汉诺塔--递归算法)

    个人觉得汉诺塔这个递归算法比电子老鼠的难了一些,不过一旦理解了也还是可以的,其实网上也有很多代码,可以直接参考.记得大一开始时就做过汉诺塔的习题,但是那时代码写得很长很长,也是不理解递归的结果.现在想 ...

  9. what' the python之递归函数、二分算法与汉诺塔游戏

    what's the 递归? 递归函数的定义:在函数里可以再调用函数,如果这个调用的函数是函数本身,那么就形成了一个递归函数. 递归的最大深度为997,这个是程序强制定义的,997完全可以满足一般情况 ...

随机推荐

  1. [第十六篇]——Docker 安装 CentOS之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 安装 CentOS CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise ...

  2. 手动制作Docker镜像

    手动制作 Docker 镜像 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器(用来用去感觉 Windows 的 Docker 出各种问题,比如使用 ...

  3. 图的遍历BFS广度优先搜索

    图的遍历BFS广度优先搜索 1. 简介 BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点"死磕到底"的思维不同,广度优先 ...

  4. use关键字在PHP中的几种用法

    在学习了和使用了这么多年的PHP之后,您知道use这个关键字在PHP中都有哪些用法吗?今天我们就来看一下它的三种常见用法. 1. 用于命名空间的别名引用 // 命名空间 include 'namesp ...

  5. javascript 标签切换

    * index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  6. jmeter性能实战

    概述 性能测试: 通过并发工具请求服务器,提前发现性能问题,优化并解决 为什么做性能测试? 常规需求 用户反馈性能问题 项目对性能不放心 性能测试的最终目标:? 性能指标分析 多快好省 项目性能场景提 ...

  7. java 工具类 验证码

    第一步: 引入工具类 工具类一: import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import jav ...

  8. appium和selenium不同与相同之处

    原文来自: https://www.cnblogs.com/zhengshuheng/p/6370398.html selenium是web端的自动化,appium是app端的自动化,它继承了webd ...

  9. P4780-Phi的反函数【dfs】

    正题 题目链接:https://www.luogu.com.cn/problem/P4780 题目大意 给出\(n\),求一个最小的\(x\)满足\(\varphi(x)=n\). 若不存在或者大于\ ...

  10. CF990G-GCD Counting【dfs】

    正题 题目链接:https://www.luogu.com.cn/problem/CF990G 题目大意 给出一棵有点权的树,对于每个\(k\)求有多条路径的点权\(gcd\)为\(k\) \(1\l ...