“经典汉诺塔”问题----(内附Java、python实现代码)

经典汉诺塔问题是什么?

废话不多逼逼,看题:

相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
在这里插入图片描述

先自己思考一小会,看看有没有想法,然后再看我逼逼

分析阶段

  1. 首先看看百度的解释:

分析:对于这样一个问题,任何人都不可能直接写出移动盘子的每一步,但我们可以利用下面的方法来解决。设移动盘子数为n,为了将这n个盘子从A杆移动到C杆,可以做以下三步:
(1)以C盘为中介,从A杆将1至n-1号盘移至B杆;
(2)将A杆中剩下的第n号盘移至C杆;
(3)以A杆为中介;从B杆将1至n-1号盘移至C杆。 [2]
这样问题解决了,但实际操作中,只有第二步可直接完成,而第一、三步又成为移动的新问题。以上操作的实质是把移动n个盘子的问题转化为移动n-1个盘,那一、三步如何解决?事实上,上述方法设盘子数为n, n可为任意数,该法同样适用于移动n-1个盘。因此,依据上法,可解决n -1个盘子从A杆移到B杆(第一步)或从B杆移到C杆(第三步)问题。现在,问题由移动n个盘子的操作转化为移动n-2个盘子的操作。依据该原理,层层递推,即可将原问题转化为解决移动n -2、n -3… … 3、2,直到移动1个盘的操作,而移动一个盘的操作是可以直接完成的。至此,我们的任务算作是真正完成了。而这种由繁化简,用简单的问题和已知的操作运算来解决复杂问题的方法,就是递归法。在计算机设计语言中,用递归法编写的程序就是递归程序。

  1. 看看的理解:

在这里我们假设A杆上有3个盘,并且叫一个和尚去完成搬盘任务:从上面移动过程可以看出,只有A3的任务完成后,A2的任务才能完成,只有第2个小和尚到第3个小和尚完成后,第1个小和尚A1的任务才能完成。只有第1个小和尚A1的任务完成,才能完成他的任务。由此可见,整个过程是一个典型的递归问题。接下来我们来分析一下。
第1个小和尚命令:
①第2个小和尚先把第一根柱子的前两个盘子移动到第二根柱子,借助第三根柱子;
②第1个小和尚自己把第一根柱子最后的盘子移动到第三根柱子;
③第2个小和尚把前两个盘子从第二根柱子移动到第三根柱子。
显然,步骤②很容易实现。
其中在步骤①中,第2个小和尚需要移动两个盘子,他就命令:
a)第3个小和尚把第一根柱子的第1个盘子移动到第三根柱子(借助第二根柱子
b)第2个小和尚自己把第一根柱子的第2个盘子移动到第二根柱子上;
c)第3个小和尚把第1个盘子从第三根柱子移动到第二根柱子。
同样,这里的第b)步很容易实现,但第3个小和尚只需要移动1个盘子,所以他也不用再下派任务了(这也是停止递归的条件,也叫递归出口

  1. 稍微抽象一点的理解:

上面的三根杆从左到右A、B、C,我们可以重新取个名字:from(从哪里开始)、temp(中转站)、dest(目的地):
开始分析:
只有一个盘子时:直接从from(A)移到dest(C )处
三个盘子时:1.将前两个盘子从from移到temp出,借助dest 2.然后将最后一个盘子从from直接移到dest处 3.现在temp处有两个盘子,而from处没有、dest有一个大盘子,这里我们可以将dest也看成是没有盘子,因为一个底座大盘子最终就是要放在dest处的。4.思维调换一下:将temp想成from 原本的from想成temp,这样又回到最开始的时候,我们不断这样递归下去就可以完成任务了。

看看代码

  • Java老大哥:
package suanFa;

import java.util.Scanner;

/**
 * “汉诺塔”问题
 * @author 作者公众号:放牛娃学编程
 *
 */

public class HanNuoTa {
//	移动函数
	public static void hanNuo(int n, char from, char temp, char dest)
	{
		if(n == 1)
		{
			System.out.println(from+"------>"+dest);
		}
		else
		{
			hanNuo(n - 1, from, dest, temp);
			System.out.println(from+"------>"+dest);
			hanNuo(n - 1, temp, from, dest);
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis();
		System.out.println("用A B C来模拟寺庙的三根柱子");
		System.out.println("请输入碟子数目");
		Scanner sc = new Scanner(System.in);
		int num = sc.nextInt();
		System.out.println("以下是我的移动顺序哟!不信你就验算一下啦啦");
		hanNuo(num, 'A', 'B', 'C');
		long end = System.currentTimeMillis();
		System.out.println("你好,上面的盘子我搬了"+((end - start)/1000)+"秒");
	}
}

运行结果:
在这里插入图片描述

  • Python新竞大哥
"""汉诺塔问题"""
import time
#移动函数
def hanNuoTa(n, froom, temp, dest):
    if(n == 1):
        print("%c----->%c" %(froom, dest))
    else:
        hanNuoTa(n - 1, froom, dest, temp)
        print("%c----->%c" %(froom,dest))
        hanNuoTa(n - 1, temp, froom, dest)
if __name__ == "__main__":
    start_time = time.time()
    print("用A B C来模拟寺庙的三根柱子")
    number = int(input("请输入碟子数目"))
    print("以下是我的移动顺序哟!不信你就验算一下啦啦")
    hanNuoTa(number, "A", "B", "C")
    end_time = time.time()
    total_time = end_time - start_time
    print("你好,上面的盘子我搬了%d秒" %total_time)

运行结果:
在这里插入图片描述
最后有兴趣一起交流的,可以关注我的公众号:这里你能够学到很实用的技巧,不是常用的我不说,年底还会抽奖送出我学过计算机相关专业的书籍福利。敬请期待!!!!
在这里插入图片描述

发布了39 篇原创文章 · 获赞 13 · 访问量 4848

猜你喜欢

转载自blog.csdn.net/qiukui111/article/details/104120484