汉诺塔问题(详细解答)

一.题目简介

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘

二.问题分析

首先是三个石柱,我们假设其分别为A,B,C
在这里插入图片描述
我们现在假设有1个盘子
在这里插入图片描述
那我们肯定是将这个盘子直接从A柱移到C柱:
在这里插入图片描述


如果有两个盘子呢?
在这里插入图片描述
我们肯定是先将A柱最上面的一个盘子从A柱移动到B柱:
在这里插入图片描述

然后再将A柱上的盘子移动到C柱:
在这里插入图片描述

最后再将B柱上的盘子移动到C柱上,这样就满足要求了:
在这里插入图片描述
那么再复杂一点,3个盘子呢?
在这里插入图片描述
我们可以先将A柱上最上面的盘子移动到C柱上:
在这里插入图片描述
再将A柱上现在最上面的移动到B柱上:
在这里插入图片描述
然后将C柱上的盘子移动到B盘上:
在这里插入图片描述
然后再将A柱最底部的盘子移动到C柱上:
在这里插入图片描述
然后是将B柱最上面的盘子移动到A柱上,
在这里插入图片描述

再将B柱上的盘子移动到C柱上:

在这里插入图片描述
最后是将A柱上的盘子移动到C柱上:

在这里插入图片描述

不知道大家有没有发现,我们在移动盘子的过程中,都会将(n-1)个盘子移动到B柱上,然后将A柱上的第n个盘子移动到C柱上。


这个时候我们就可以将其推广到n个盘子的时候,这个时候的思路是 ,我们先将A柱上的(n-1)个盘子从A柱移动到B柱上:
在这里插入图片描述

再将A柱上的第n个盘子从A柱移动到C柱上:
在这里插入图片描述

然后我们再将B柱上的(n-2)个盘子从B柱移动到A柱上:
在这里插入图片描述

再将B柱上的第(n-1)个盘子从B柱移动到C柱上:
在这里插入图片描述

如此往复下去,直到n个盘子全部按照大小移到C柱上。

当我们分析到n个盘子的时候,就应该能意识到这是一个函数递归的问题,函数递归最主要就是大事化小思想,我们可以看到要实现n个盘子的移动时,我们其实是将其看成了两部分(第n个盘子和(n-1)个盘子),我们是将(n-1)个盘子看成一个整体,所以我们在处理n个盘子的移动时,简化成了2个盘子的移动,这样第n个盘子就很好移动到它该处的位置,然后再将剩余的(n-1)个盘子看成第n-1个盘子和(n-2)个盘子(同样是将(n-2)个盘子看成一个整体),就这样层层递归下去,将大事件化简成小事件处理。

三.代码实现

C语言代码实现:

#define _CRT_SECURE_NO_WARNINGS 1


//汉诺塔问题
void move(char pos1, char pos2)
{
	printf(" %c->%c ", pos1, pos2);
}
/*
N:有N个盘子
pos1:起始位置
pos2:中转位置
pos3:目标位置

这里我们假设有n个盘子,我们先将n-1个盘子从A上移到B上,
再将A上的第n个盘子从A移到C上,然后我们再将B上的n-2个
盘子从B上移到A上,再将B上的第n-1个盘子从B上移到C上,
如此往复下去,直到n个盘子全部按照大小移到C盘上


*/
void Hanoi(int N, char pos1, char pos2, char pos3)
{
	if (N == 1)
	{
		move(pos1, pos3);
	}
	else
	{
		Hanoi(N - 1, pos1, pos3, pos2);
		//现在盘子都在pos1上,现在通过中转位置pos3,将n-1个盘子移动到目标位置pos2上。
		move(pos1, pos3);
		//此时我们已将将n-1个盘子挪开了,只剩下第n个盘子了,直接将第n个盘子移动到目标盘即可。
		Hanoi(N - 1, pos2, pos1, pos3);
		//现在我们还有n-1个盘子需要挪动,现在我们的n-1个盘子在pos2上,
		//我们需要通过中转位置pos1来将n-2个盘子移动到目标位置pos3.
	}
	
}

#include<stdio.h>

int main()
{
	int N = 0;
	scanf("%d", &N);
	Hanoi(N, 'A', 'B', 'C');
	return 0;
}

Java代码实现:

import java.util.Scanner;

public class Text {
    public static void main4(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        Hanoi(n,'A','B','C');
    }
    public static void Hanoi(int n,char pos1,char pos2,char pos3){
        if(n==1){
            move(pos1,pos3);
        }else{
            Hanoi(n-1,pos1,pos3,pos2);
            move(pos1,pos3);
            Hanoi(n-1,pos2,pos1,pos3);
        }
    }
    public static void move(char pos1,char pos2){
        System.out.println(pos1+"->"+pos2);
    }
}
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

论迹

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值