C语言每日一练——第88天:汉诺塔问题(河内塔)

🌟 前言

大家好,我是Edison😎

今天是C语言每日一练,第88天!

Let’s get it!



1. 题目描述

汉诺塔问题

解题之前,我们先来了解一下 汉诺塔 到底是什么?

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

2. 解题思路

思路很简单:有三根相邻的柱子,从左到右分别为:托盘A托盘B托盘C
 
托盘A按照“从下到上、从大到小”叠放着3个不同大小的盘子;👇
在这里插入图片描述
第一步:将盘子1从托盘A移动至托盘C👇
在这里插入图片描述
第二步:将盘子2从托盘A移动至托盘B👇
在这里插入图片描述
第三步:将盘子1从托盘C移动至托盘B👇
在这里插入图片描述
第四步:将盘子3从托盘A移动至托盘C👇
在这里插入图片描述
第五步:将盘子1从托盘B移动至托盘A👇
在这里插入图片描述
第六步:将盘子2从托盘B移动至托盘C👇
在这里插入图片描述
第七步:将盘子1从托盘A移动至托盘C👇
在这里插入图片描述
注:此过程图是我从网上找的,实在是难得画啦😂)

3. 动图演示

在这里插入图片描述

是不是很简单?

我们从上面移动的过程中,可以看到,托盘B始终作为一个过渡的存在,并且可以把它想象成中转柱
 
那么我们就可以这样理解:
 
托盘A:起始柱A;
 
托盘B:中转柱B;
 
托盘C:目标柱C
 

4. 代码实现

那么我们怎么用代码来实现呢?

这是一个非常经典的递归问题。
 
假设有n个盘子,需要把这些盘子从第一根起始柱A移动到第三根目标柱C中。
 
1、首先需要把n-1个盘子移动到第二根中转柱B上;
 
2、再把最后一个也就是最大的那一个盘子移动到第三根目标柱C上;
 
3、最后再把剩下的n-1个盘子移动到第三根目标柱C上。
 
我们定义 f ( n ) f(n) f(n)是需要移动的次数;
 
f ( 1 ) = 1 , f ( 2 ) = 3 , f ( 3 ) = 7 f(1) = 1,f(2) = 3,f(3) = 7 f(1)=1f(2)=3f(3)=7

f ( n ) = 2 f ( n − 1 ) + 1 f(n) = 2f(n-1)+1 f(n)=2f(n1)+1

📝代码示例

这里拿3个盘子为例

#include <stdio.h>

void move(int n, char pos1, char pos3)
{
    //打印移动的过程
    // 1代表上面最小的盘子
    // 2代表中间位置的盘子
    // 3代表下面最大的盘子
    printf("盘子%d: 从 %c柱 移动到 %c柱\n", n, pos1, pos3);

}

void Hanoi(int n, char pos1, char pos2, char pos3)
{
    //如果是1个盘子,直接从起始柱A移动到目标柱C
    if (n == 1) 
    {
        move(n, pos1, pos3);
    }
    else
    {
        //如果盘子大于1个,需要把n-1个盘子,从起始柱pos1,通过目标柱pos3,移动到中转柱pos2
        Hanoi(n-1, pos1, pos3, pos2); 

        //此时pos1上的n-1个盘子全部移动pos2上去了,那么可以直接把pos1上剩下的1个盘子,直接移动到pos3上
        move(n, pos1, pos3);

        //把pos2剩下的n-1个盘子,通过中转位置pos1,移动到目标位置pos3
        Hanoi(n-1, pos2, pos1, pos3);
    }
}

int main()
{
    //盘子个数
    int n = 3;

    //起始柱A
    char pos1 = 'A';

    //中转柱B
    char pos2 = 'B';

    //目标柱C
    char pos3 = 'C';

    printf("移动%d个盘子的步骤如下↓\n", n);

    //汉诺塔函数
    Hanoi(n, pos1, pos2, pos3);

    return 0;
}

运行结果👇

在这里插入图片描述
完整代码贴图👇
在这里插入图片描述

5. 特性总结

回到我们这个题的本身,僧侣要移动64个金片,到底需要多久?
 
对于汉诺塔问题, f ( n ) = 2 64 − 1 f(n) = 2^{64}-1 f(n)=2641 这是一个什么概念?
 
即使是每微秒移动一次, 也需要5000世纪的时间, 可能到那个时候,世界也许真的将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽🤣
 
不信的话,大家可以去试一试🐶

以上内容如有转载或引用请私聊说明并标明出处😘)

  • 236
    点赞
  • 444
    收藏
  • 打赏
    打赏
  • 113
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论 113

打赏作者

Albert Edison

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值