算法之路(四)----汉诺塔(又称河内之塔)

2023-05-16

汉诺塔是很简单也很经典的算法之一。
汉诺塔是根据一个传说形成的数学问题:
有三根杆子A,B,C 。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
* 1 每次只能移动一个圆盘;
* 2 大盘不能叠在小盘上面。

提示:可将圆盘临时置于B杆,也可以将A杆移除的圆盘重新移动回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?

3个圆盘的汉诺塔移动

4个圆盘的汉诺塔移动

传说

最早发明这个问题的人是法国数学家爱德华*卢卡斯。
传说印度某间寺院有三根柱子,上串64个金盘。寺院里的僧侣依照一个古老的预言,以上述规则移动这些盘子;预言说当这些盘子移动完毕,世界就会灭亡。这个传说叫做梵天寺之塔问题(Tower of Brahma puzzle)。但不知道是卢卡斯自创的这个传说,还是他受他人启发。
若传说属实,僧侣们需要264− 1步才能完成这个任务;若他们每秒可完成一个盘子的移动,就需要5849亿年才能完成。整个宇宙现在也不过137亿年。
这个传说有若干变体:寺院换成修道院、僧侣换成修士等等。寺院的地点众说纷纭,其中一说是位于越南的河内,所以被命名为“河内塔”。另外亦有“金盘是创世时所造”、“僧侣们每天移动一盘”之类的背景设定。
佛教中确实有“浮屠”(塔)这种建筑;有些浮屠亦遵守上述规则而建。“河内塔”一名可能是由中南半岛在殖民时期传入欧洲的。

解答

如取N=64,最少需移动264− 1次。即如果一秒钟能移动一块圆盘,仍将需5849.42亿年。目前按照宇宙大爆炸理论的推测,宇宙的年龄仅为137亿年。
在真实玩具中,一般N=8;最少需移动255次。如果N=10,最少需移动1023次。如果N=15,最少需移动32767次;这就是说,如果一个人从3岁到99岁,每天移动一块圆盘,他最多仅能移动15块。如果N=20,最少需移动1048575次,即超过了一百万次。

解法

解法的基本思想是递归。假设有A、B、C 三个塔,A塔有N块盘,目标是把这些盘全部移动到C塔。那么先把塔顶部的N-1块盘移动到B塔,再把A塔剩下的大盘移动到C,最后把B塔的N-1块盘移动到C。
每次移动多于一块盘时,则再次使用上述算法来移动。

怎么来理解呢?
我们可以倒着理解,要将A塔上的所有圆盘移动到C塔,且所有圆盘是下大上小。那么必定有一个过程是最大的圆盘(也就是第N个圆盘)从A移动到C。那么必须保证上面的N-1个圆盘全在B塔,且圆盘满足上面小,下面大。当第N个圆盘从A移动到C之后,又得把N-1个圆盘从B塔移动到C塔,这样工作就完成了。
但是怎么把A塔上的N-1个圆盘移动到B塔呢?
这里需要一点想象力,可以想象成只有N-1个圆盘,从A塔移动到B塔(此时的B塔其实就相当于上面的C塔),我们称A塔为A1塔,B塔为C1塔,C塔为B1塔,那么问题就变成了如何将N-1个盘从A1塔移动到C1塔?
同样的需要将上面的N-2个圆盘从A1塔移动到B1塔,然后将第N-1个圆盘从A1塔移动到C1塔,然后再将B1塔上的N-2个圆盘移动到C1塔。
同理,递推第N-2个塔…..。

将 B塔上的 N-1个盘,移动到C塔的过程与上面原理一样。

递归解

以Objective-C语言实现:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    int n = 9;
    [self hannoi:n from:@"A" buffer:@"B" to:@"C"];
    NSLog(@"一共 %d 步",count);
}

- (void)hannoi:(int)n from:(NSString *)from buffer:(NSString *)buffer to:(NSString *)to
{
    if (n == 1) {
        NSLog(@"Move disk %d from %@ to %@", n, from, to);
    } else {
        [self hannoi:n-1 from:from buffer:to to:buffer];
        NSLog(@"Move disk %d from %@ to %@", n, from, to);
        [self hannoi:n-1 from:buffer buffer:from to:to];
    }
}

console : 一共 511

以C++语言实现:

using namespace std;
#include <iostream>
#include <cstdio>

void hannoi (int n, char from, char buffer, char to)
{
    if (n == 1) {
        cout << "Move disk " << n << " from " << from << " to " << to << endl;
    } else {
        hannoi (n-1, from, to, buffer);
        cout << "Move disk " << n << " from " << from << " to " << to << endl;
        hannoi (n-1, buffer, from, to);
    }
}

int main()
{
    int n;
    cin >> n;
    hannoi (n, 'A', 'B', 'C');
    return 0;
}

通过以上递归过程可知hannoi(n) = 2 * hannoi(n-1) + 1 ,hannoi(n) = 2n-1 + 2n-2 + 2n-3+ …… + 22 + 2 +1。
对等比数列求和得出hannoi(n) = 2n -1。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法之路(四)----汉诺塔(又称河内之塔) 的相关文章

  • 图像的灰度化、二值化

    目录 1 图像像素点 2 灰度化 3 二值化 4 使用open cv库进行图片的灰度化 二值化 4 1 将图片转换为灰度图 4 2 将灰度图转换为二值化图图片 1 图像像素点 在图像处理中 xff0c 用RGB三个分量 xff08 R xf
  • 【嵌入式】stm32程序跳转实验

    嵌入式 stm32程序跳转实验 菜老越 于 2019 04 23 17 54 56 发布 2888 收藏 22 分类专栏 xff1a 嵌入式 文章标签 xff1a keil stm32 程序跳转 IAP BootLoader 版权 嵌入式
  • C++/C语言实现HTTP的GET和POST请求

    阅读目录 HTTP请求和IP TCP 实现GET请求 实现POST请求 xff1a 参考 xff1a 回到顶部 HTTP请求和IP TCP 所谓的HTTP协议是基于IP TCP协议的 xff0c 所以要获取远端的html数据只要创建sock
  • C++ 简单实现HTTP GET/POST 请求

    HTTP 超文本传输协议 是一种客户端与服务端的传输协议 xff0c 最早用于浏览器和服务器之间的通信 xff0c 后来因为其使用灵活 方便等特点 xff0c 广泛用于客户端与服务端的通信 文章将简单介绍HTTP协议 xff0c 同时以C
  • 分布式系统架构简单介绍

    目录 xff1a 一 什么是分布式系统 xff1f 二 为什么要走分布式系统架构 xff1f 三 系统如何进行拆分 xff1f 四 分布式之后带来的技术挑战 xff1f 一 什么是分布式系统 xff1f 在谈分布式系统架构前 xff0c 我
  • 使用javascript实现对于chineseocr的API调用

    ChineseOCR在线API 网页地址 界面 提供多种接口调用方式 xff0c 比如在线调用 Javascript api调用 curl api调用和python api调用四种方式 xff0c 本次使用javascript api调用的
  • Qt-QMessageBox用法详解

    QMessageBox 是 Qt 框架中常用的一个类 xff0c 可以生成各式各样 各种用途的消息对话框 xff0c 如图 1 所示 图 1 QMessageBox消息对话框 很多 GUI 程序都会用到消息对话框 xff0c 且很多场景中使
  • C++中UDP通讯详解

    C 43 43 Socket编程及TCP UDP通信代码实现 一 简介 Socket编程的目的是使网络的进程进行通信 xff0c 基于TCP IP协议簇 xff0c 通过三元组 xff08 ip地址 协议 端口 xff09 标志进程 xff
  • sphinx写文档的简单尝试--index.rst的内容分析

    先说简单的结论 xff0c rst上手难度远高于markdown 功能扩展完爆markdown 在安装sphinx后 xff0c 开始编写shpinx的第一步 xff0c 就是使用sphinx quickstart来生成配置文件 我的目录结
  • 读书笔记:嵌入式常用算法_note_1

    目录 折线插值 抛物线插值 折线插值 include lt stdio h gt define N 10 折线由10段线段组成 即有11个插值节点 float w 61 10 0 插值节点间隔为10 0 即 w 61 y1 y0 61 10
  • Linux下免费git工具集合

    该博文来自于ieayoio的博客 xff1a http www ieayoio com win和mac下的git图形工具都有挺多的 xff0c 然而对于因git而生的Linux xff0c git的图形工具普遍被认为相当落后 xff0c 然
  • [rospack] Error: package ‘.....‘ not found

    在ros编程中如果报出 rospack Error package 39 39 not found 某个包没有找到 xff0c 则有一下几方面的原因 1 包名写错了2 工作空间真的没有这个包存在3 包所在的ros工作空间没有在ros环境中
  • Pytorch中TypeError: 'DataLoader' object is not subscriptable错误

    今天学习pytorch遇到以下问题 TypeError 39 DataLoader 39 object is not subscriptable 一开始设置的参数如下 cifar train 61 DataLoader cifar trai
  • undefined reference to `vtable for fmt::v7::format_error‘

    在使用eigen3和sophus 库时 xff0c 如遇到以下错误 undefined reference to 96 vtable for fmt v7 format error 39 undefined reference to 96
  • 什么是嵌入式软件工程师?需具备哪些能力?

    计算机嵌入式逐渐被大家认可 xff0c 然而嵌入式软件工程师到底是什么 做一个好的嵌入式软件工程师又需要具备哪些能力呢 今天尚观教育小编跟大家聊一聊 1 嵌入式软件工程师是什么 嵌入式系统一般由嵌入式微处理器 外围硬件设备 嵌入式操作系统以
  • STM32串口中断接收到的16进制数据如何判断

    最近用到了一款WIFI摄像头 xff0c 这款摄像头可以通过手机app控制 xff0c 从而使串口发送指定的数据 xff0c 这样会以来就可以通过这款摄像头在手机app上控制小车的前后左右 xff0c 还可以实现无线图传的功能 这款摄像头通
  • ROS Robotics By Example No transform from [left_wheel] to [base_link]

    1 问题描述 在第二章中搭建双轮机器人 lt xml version 61 34 1 0 34 gt lt robot name 61 34 dd robot 34 gt lt base link gt lt link name 61 34
  • ROS中的坐标转换1

    1 坐标转换 坐标转换是指坐标系之间的平移以及旋转关系 xff0c 如坐标系A B C A xff0c B之间存在一个转换关系 T B A T B A T B A B与
  • 可用的双目标定代码(先单目标定再双目标定)

    最近做双目项目需要进行标定 xff0c 网上查看一些资料 目前所用是先进行单目标定 xff0c 然后在进行双目标定 代码如下 xff0c 配以后使用 span class token comment biaoding cpp span sp
  • 使用Docker配置SVO SLAM1与SVO SLAM2的运行环境

    1 ROS docker的获取 sudo docker pull osrf ros noetic desktop full 2 进入docker 2 1 使docker可以使用宿主机的图形界面 xff08 具体可以查看docker使用 xf

随机推荐

  • ubuntu下VScode使用Clang-Format进行代码格式化

    1 安装 Clang Format 在vscode中安装 Clang Format插件 2 在系统中安装Clang Format sudo apt get install clang format 3 生成Clang Format文件 格式
  • rviz远程查看机器人显示

    1 使用rviz远程查看机器人显示 1 1 已有设备 本地主机 ip为192 168 2 102 机器人主机 ip192 168 2 104 主机名 xff1a hhh 2 配置本地 bashrc sudo gedit bashrc 输入
  • Python中使用SQLAlchemy连接Mysql数据库(单表操作)

    一 xff0c SQLAlchemy的安装 使用 easy install sqlalchemy 或 pip install sqlalchemy 如果出现什么错 xff0c 就进去root用户下进行安装试试 xff0c 或者网上查查 gt
  • 1>MSVCRTD.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 _main,该符号在函数 “int __cdecl invoke_main(void)“

    在使用SDL库的时候会在编译时报出以下错误 1 gt MSVCRTD lib exe main obj error LNK2019 无法解析的外部符号 main xff0c 该符号在函数 int cdecl invoke main void
  • 在web页面中播放rtsp直播数据流方法

    WEB播放RTSP直播数据流方法 在html技术中目前是无法直接使用现有的web技术进行播放rtsp直播数据流的 xff0c 下面总结了可以是web播放rtsp直播流的方法 只是自己备用 1 xff0c 视频播放功能使用的库 WebChim
  • 天猫精灵智能家居对接,及天猫iot官网配置图文讲解(一)

    天猫智能家居对接 1 1 介绍 这篇文章主要是介绍 xff0c 如何使用java对接天猫精灵智能家居提供的api 这么做的好处就是能让用户通过天猫精灵发送命令到我们的服务器 xff0c 然后操控设备执行一系列的命令 xff0c 当然这些功能
  • 新手学习嵌入式开发要学什么

    最近遇到很多处于迷茫中的新手 xff0c 在纠结要不要去学嵌入式 xff0c 主要问题在于嵌入式的门槛非常高 xff0c 经验少 或者非电子专业投身嵌入式行业能否发展下去 现在嵌入式开发行业的确发展很好 xff0c 大多数从业者都是科班出身
  • 天猫精灵智能家居对接,及天猫iot官网配置图文讲解(二)

    天猫精灵智能家居对接 及天猫iot官网配置图文讲解 xff08 二 xff09 2 天猫精灵设备对接 2 1 介绍 上一章里 xff0c 我已经讲了天猫精灵的技能配置 xff0c 设备创建 xff0c 登录验证这三个部分做了 xff0c 此
  • [一] Nuttx 系统结构简析和开发步骤

    文章目录 一 背景二 Nuttx系统分层三 各层的作用四 各层之间的粘合剂五 总结 amp 开发步骤 一 背景 最近在自己开发基于Nuttx的四轴飞行器控制系统 慢慢的对Nuttx有了自己的理解 二 Nuttx系统分层 NSH Nuttx
  • Ardupilot编译流程分析

    lt 61 2 61 gt gt gt gt gt gt gt 编译流程分析 lt 61 2 61 gt gt gt gt gt gt gt lt 1 gt 在ardupilot ArduCopter 键入 xff1a make px4 v
  • 《cmake调用shell》

    1 CMakeLists txt add custom target config ALL COMMAND bash x sh 2 shell File Name x sh Author XXDK Created Time Wed 01 N
  • Ardupilot之cpu外设基础抽象聚合类 HAL.h

    libraries AP HAL HAL h 定义了所有外设的基础抽象类集合 一个 HAL 抽象类世界 xff0c 由 HAL 层的cpu外设的抽象类基础组件组聚而成 xff1b 也就是一个 HAL 派生类子对象 代表了一个 cpu 的所有
  • 一次Ajax报错:“存储空间不足,无法完成此操作”的解决经验

    连续几天我们收到几位客户的问题工单 xff0c 问题描述都类似 xff0c 都是在做登陆或者交易时报脚本错误 xff0c 交易无法正常执行 我们 远程协助 客户机器时 xff0c 调试发现都是ajax代码出错 xff0c 错误如下 xff1
  • Java异常的另类用法(一)

    异常在我们的代码中是不可避免的 xff0c 有些异常可以忽略 xff0c 多数的异常我们要显式处理 xff08 至少要记录日志 xff0c 以便后面排查问题 xff09 xff0c 这里我们不是要细说异常的处理规范 xff0c 而是使用异常
  • 使用POI在Excel单元格插入符号(Symbol)

    最近看到有人在 技术问答 上提问怎么用java在excel中插入打勾符号 xff1f 我想解决这个问题并不难 我们先打开一个excel文件 xff0c 在里面插入特定符号 xff0c 然后用poi xff08 其他的技术也可以 xff09
  • Eclipse下C语言的Socket编程(Winsock,gcc)问题总结

    最近心血来潮想从新温习一下C语言 xff08 工作后一直用Java xff0c 其实大学时C语言课程也没好好上 xff0c 正经的代码基本没写过 xff0c 惭愧啊 xff01 xff09 xff0c 找了些小例子 xff0c 修修改改 x
  • 各种哈希函数的java实现

    收集整理 public class HashUtils br private static final int crctab 61 0x00000000 0x77073096 0xee0e612c 0x990951ba br 0x076dc
  • libssl.so.10缺失库文件的解决办法

    libssl so 10缺失库文件的解决办法 在RHEL6 5中对openssl进行了升级 xff0c 如果老版本是OpenSSL 1 0 1e fips 那直接安装最新的openssl 1 0 1g 1 x86 64 rpm就行了 xff
  • Nvidia Jetson Nano入门与使用

    Pre xff1a Nvidia Nano板等了好久 xff0c 国内终于便宜了一点 刚从网上买一个 xff0c 准备替换掉Nvidia TX2开发板 xff08 因为目前的算法在Nano开发板上跑应该没有问题 xff09 打开包装 xff
  • 算法之路(四)----汉诺塔(又称河内之塔)

    汉诺塔是很简单也很经典的算法之一 汉诺塔是根据一个传说形成的数学问题 xff1a 有三根杆子A xff0c B xff0c C A杆上有N个 N gt 1 穿孔圆盘 xff0c 盘的尺寸由下到上依次变小 要求按下列规则将所有圆盘移至C杆 x