汉诺塔问题,对递归的进一步思考

传送门

题目意思并不难理解,有三根柱子 a , b , c。 a 柱子上有一堆从小到大排列的圆盘,把圆盘从下面开始按大小顺序重新摆放在 c 柱子上。并且规定,任何时候,

小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?

初次接触类似的问题,乍看之下肯定会感觉无从下手。

假设有64个圆盘,要把64个圆盘从a柱子移动到c柱子上,第一步应该怎么做?虽然可以肯定,第一步唯一的选择是移动a最上面的那个圆盘,但是应该将其移到b还是c呢?很难确定。因为接下来的第二步、第三步……直到最后一步,看起来都是很难确定的。能立即确定的是最后一步:最后一步的盘子肯定也是a最上面那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。也许你会说,管他呢,先随便试着移动一下好了。如果你这么做,你会发现,接下来你会面临越来越多类似的选择,对每一个选择都“试”一下的话,你会偏离正确的道路越来越远,直到你发现你接下来无法进行为止。

一股脑地考虑每一步如何移动很困难,我们可以换个思路。先假设除最下面的盘子之外,我们已经成功地将上面的63个盘子移到了b柱,此时只要将最下面的盘子由a移动到c即可。

当最大的盘子由a移到c后,b上是余下的63个盘子,a为空。因此现在的目标就变成了将这63个盘子由b移到c。这个问题和原来的问题完全一样,只是由a柱换为了b柱,规模由64变为了63。因此可以采用相同的方法,先将上面的62个盘子由b移到a,再将最下面的盘子移到c……对照下面的过程,试着是否能找到规律:

  1. 将b柱子作为辅助,把a上的63个圆盘移动到b上
  2. 将a上最后一个圆盘移动到c
  3. 将a作为辅助,把b上的62个圆盘移动到a上
  4. 将b上的最后一个圆盘移动到c
  5. ......

 

也许你已经发现规律了,即每次都是先将其他圆盘移动到辅助柱子上,并将最底下的圆盘移到c柱子上,然后再把原先的柱子作为辅助柱子,并重复此过程。
这个过程就是递归,即定义一组基本操作,这组操作将规模小一点(或大一点)的操作当做一个整体——无需关心它的细节,只当它已经完成了——然后执行剩下的操作。而在更小或更大的规模中也依此操作,直到规模达到预定值。

代码

复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1;

void solve(int n, char a, char b, char c)
{
    if (n == 1)
    {
        printf("No.%d disk: %c->%c\n", n, a, c);
    }
    else
    {
        solve(n - 1, a, c, b);//  a移到b,c为辅助柱
        printf("No.%d disk: %c->%c\n", n, a, c);
        solve(n - 1, b, a, c); // b移到c,a为辅助柱
    }
}

int main()
{
    int n;
    cin >> n;
    solve(n, 'a', 'b', 'c');
    return 0;
}
复制代码

 

posted @   黎_lyh  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示