递归问题的实际运用:汉诺塔问题

简介: 递归问题的实际运用:汉诺塔问题

先来看看什么是汉诺塔问题:


来源:


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


5f13ddb1c7514e359ae04a7719445aa2.png



分析:对于这样一个问题,任何人都不可能直接写出移动盘子的每一步,但我们可以利用下面的方法来解决。设移动盘子数为n,为了将这n个盘子从A杆移动到C杆,可以做以下三步:


(1)以C盘为中介,从A杆将1至n-1号盘移至B杆;


(2)将A杆中剩下的第n号盘移至C杆;


(3)以A杆为中介;从B杆将1至n-1号盘移至C杆。


我们画个图示意一下:


如果只有一个盘子,那么我们直接将盘子移动C柱就行。



2ba867cf1d7248ed905d4ed7e2bc8070.png



a35270e06ebd468d9bcb9ad3b6469dcc.png

也就是A -> C 。

如果有两个盘子,我们该怎么挪呢?


f6df5cd434a34d0d8224be79015c5cd6.png

1.先将红盘移动到B柱。

A -> B



c750843b598f45bd87a90b3a726495ae.png


2.再将绿盘移到C柱。

       A -> C



20be9fc2f34b442586ca6ec6a174abb1.png


3.最后将B柱的红盘移到C柱。

       B -> C


a3f811636860452f9aab67c1229a25db.png




如果有三个盘子:

一定要保证大的在下,小的在上。


  1. A -> C



6ce615925eec4bf99bb222d6308d1b25.png


2.A ->B


1d9876882b5145f7b5ff972bf1b383be.png

3.C ->B


a3d1dfa6f3524c64826008de7101b9f4.png


4.A->C


d21a7953fa53420c9131f64a5a17834a.png

5.B -> A


d2d7b810a6c846d3a075439b296dab4c.png


6. B -> C

7. A -> C



8f952a2b02314da68a2799ec2d45d3e3.png



如果是四个柱子:


也是这种思路,我们可以把他们放到一起来对比。


1个盘子 A -> B 移动一次


2个盘子 A -> B A->C B->C 移动三次


3个盘子 A-> C A->B C->B A->C B->A B->C A->C 移动七次 公式为:2^n-1


那么如果有64个盘子我们看看需要移动多少次:


cf40ed0338e14c25a52e608e9c6ec261.png


这太大了,用我们一般的计算机来跑也需要数百年。

那么我们的代码该怎么去写呢?

public class demo {
    /**
     *
     * @param n:盘子个数
     * @param pos1:起始位置
     * @param pos2:中转位置
     * @param pos3:目的位置
     */
    public static void Hanoi(int n,char pos1,char pos2,char pos3){
        if (n == 1 ){
            move(pos1,pos3);
            return ;
        }
        //无论这个有多少个盘子,我都需要借助pos3 移动到pos2 上,只留下最底下,最大的那个盘子
        Hanoi(n-1,pos1,pos3,pos2);
        //将这个最大的盘子移动到pos3 上
        move(pos1,pos2);
        //于是问题转化成了:
        Hanoi(n-1,pos2,pos1,pos3);
        //具体是怎么操作的我们不用管
    }
    public static void move(char pos1,char pos2){
        System.out.print(pos1 + "->" + pos2 +" ");
    }
    public static void main(String[] args) {
        Hanoi(2,'A','B','C');
        System.out.println();
        Hanoi(4,'A','B','C');
        System.out.println();
    }
}

883bcba12e0a4955b8a007369694306f.png


如果这里是 64 个盘子,肯定是跑不完的。


153aca02965d4b4b8a638c345d23d1e9.png



相关文章
|
5月前
|
算法 C语言
汉诺塔问题(函数递归)
汉诺塔问题(函数递归)
42 0
|
6月前
|
Java Python
汉诺塔递归问题,递归思路详解
汉诺塔递归问题,递归思路详解
69 0
|
6月前
|
机器学习/深度学习
利用函数递归求汉诺塔问题
利用函数递归求汉诺塔问题
54 0
汉诺塔 递归问题
汉诺塔 递归问题
79 0
|
C++ C语言
你是真的“C”——函数递归详解汉诺塔
利用函数递归手把手求解汉诺塔
107 0
你是真的“C”——函数递归详解汉诺塔
|
C语言
【C】青蛙跳台阶和汉诺塔问题(递归)
【C】青蛙跳台阶和汉诺塔问题(递归)
122 0
【C】青蛙跳台阶和汉诺塔问题(递归)
汉诺塔(递归+ 非递归版)
汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题。在A,B,C三根柱子上, 有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔。 游戏中的每一步规则如下:
232 1
汉诺塔(递归+ 非递归版)