汉诺塔(hanoi)问题从0到1详解

简介: 汉诺塔(hanoi)问题从0到1详解

一、汉诺塔问题的起源



有没有人会和我一样,看到这个问题就会想到这个问题是怎么形成的呢?是谁提出来的呢?或者是来源是呢?于是我查询了一下,跟大家简单叙述一下。


 传说在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。


  当然,如果真的要是把64片金片由一根针上移到另一根针上,并且始终保持上小下大的顺序。那么到底要移多少次呢?假如一秒移一次,还是每一次都移的是正确的前提下,要移动多长时间呢?也就是传说的移动结束后世界就会消灭,那我们来看看到底还有多长时间世界会消灭!


二、汉诺塔问题的实现

一、汉诺塔问题的要求


 如下图,把A柱子上的盘子借助B柱子移动到C柱子上面。移动的要求:每一步只能移动一个盘子,同时必须满足大盘子在小盘子的下面。我们先从简单的开始一步一步分析。

二、汉诺塔思路从易到难


1、一个盘子的实现

   当只有一个盘子的时候很简单,直接从A移动到C上。如图:

2、两个盘子的实现


  当有两个盘子的时候,我们就要借助B柱子了。接下来,我将移动的步骤直接简化表达。

  1. A->B
  2. A->C
  3. B->C

第一步:

第二步:



0e510eed4ff64a6c864ceb6d7a08f236.png



第三步:

  第三步移动结束后就算完成了。


3、三个盘子的实现

  我么你来看一下三个盘子的实现,A->C,A->B,C->B,A->C,B->A,B->C,A->C.

如图:

第一和第二步:

第三步:

第四步:



3542290c04bc478cb1607996e8251b4b.png

注意!!!!!!


  到这里我们先简单总结一下:我们移动的思路其实就是先把除了最下面的盘子,也是就上面的两个盘子借助柱子C移动到柱子B上,然后我们再把最下面的盘子直接移动到柱子C上,最后我们只需要把柱子B上的盘子借助柱子A 移动到柱子C上即可。


 第五和第六步:


90c8f59bdd7b47629f77ebf578df6302.png



第七步:

总览图:

 

 到这里我们就移动和结束了。


4、 n个盘子的实现

 我们来看一下n个盘子的实现思路。总上我们可以总结出:当有n个盘子的时候,我们先把除了最底下的盘子之外的n-1个盘子借助柱子C移动到柱子B上,然后再把最后一个盘子移动到柱子C上。到这里我们只需要将柱子B上的n-1个盘子借助柱子A移动到柱子C上即可。


 如图:

第一步:

第二步:

第三步:

  归根结底,我们上面用到了把大化小,从而一步一步解决的思想。这不就是递归吗!我们来看一下代码的实现。可以结合着代码一起理解一下哦。

三、汉诺塔代码的实现

#include<stdio.h>
void move(char pos1, char pos2)
{
  printf("%c->%c ", pos1, pos2);
}
void hanoi(int n, char A, char B, char C)
{
  if (n == 1)
    move(A, C);
  else
  {
    hanoi(n - 1, A, C, B);//n-1个盘子从柱子A通过柱子C移动到柱子B上
    move(A, C);           //最底下的盘子移动到C上
    hanoi(n - 1, B, A, C);//n-1个盘子从柱子B通过柱子A移动到柱子C上
  }
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  hanoi(n, 'A', 'B', 'C');
  return 0;
}


四、尾言



通过上面的规律我们可以看出:假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2^n-1。n=64时,假如每秒钟一次,还是移动正确的情况下,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下:18446744073709551615秒,这表明移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年。太阳系的预期寿命据说也就是数百亿年。


 要是僧侣们预言是准确的,那我们何乐而不为呢?当然,预言终究是是预言,我们这个时代还是要讲究科学依据的。


 好了,汉诺塔的问题我们就讲解到这里,希望这篇文章对你很好的帮助,感谢阅读!

相关文章
|
Linux
软件包管理工具 - rpm
【1月更文挑战第16天】
398 0
|
Kubernetes 负载均衡 网络协议
在K8S中,Service的类型有哪些?
在K8S中,Service的类型有哪些?
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
当前AI大模型在软件开发中的创新应用与挑战
【10月更文挑战第31天】2024年,AI大模型在软件开发领域的应用取得了显著进展,从自动化代码生成、智能代码审查到智能化测试,极大地提升了开发效率和代码质量。然而,技术挑战、伦理与安全问题以及模型可解释性仍是亟待解决的关键问题。开发者需不断学习和适应,以充分利用AI的优势。
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
397 2
|
Shell Android开发
安卓scheme_url调端:在AndroidManifest.xml 中如何配置 Intent-filter?
为了使Android应用响应vivo和oppo浏览器的Deep Link或自定义scheme调用,需在`AndroidManifest.xml`中配置`intent-filter`。定义启动的Activity及其支持的scheme和host,并确保Activity可由外部应用启动。示例展示了如何配置HTTP/HTTPS及自定义scheme,以及如何通过浏览器和adb命令进行测试,确保配置正确无误。
|
数据挖掘 Python
四分位距方法
四分位距方法
|
机器学习/深度学习 数据可视化 算法
生成对抗网络项目:1~5(1)
生成对抗网络项目:1~5(1)
321 0
|
JavaScript 前端开发 Java
Springboot & MySQL & Mybatis 学生管理系统
本学生管理系统主要是以年级、班级为单位,进行老师和学生信息记录和统计功能。项目采用前后端分离架构思想,前端采用HTML+CSS+VUE来实现页面效果展示,后端采用SpringBoot+MybatisPlus框架实现数据存储等服务。存储层使用高性能的MySQL,服务器使用SpringBoot内置的Tomcat9.x,项目构建工具使用Maven来管理jar包和项目构建。点击学生管理系统获取资源!Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心
735 0
|
SQL 缓存 监控
性能测试(23)——完整性能项目案例
性能测试需求分析与传统的功能测试需求有所不同 功能测试需求分析:重点在于分析被测系统的功能是否满足产品功能需求规格(正向、逆向) 性能测试需求分析:重点在于分析被测系统是否能满足特定的业务需求场景(时间、资源) 需要从业务场景、程序代码、服务器、硬件配置等多个维度分析系统可能存在性能瓶颈
4938 1
|
移动开发 运维 小程序
速抢!初创企业专享的0元建站豪礼!
今天,小云要向各位看官推荐一个助力企业降本增效开拓私域流量的方式——
306 0