汉诺塔问题

Posted mydesky2012

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汉诺塔问题相关的知识,希望对你有一定的参考价值。

1 问题描述

有A,B,C三个柱子,A柱子上从上到下,从小到大排列着n个圆盘。现要求将A柱子上的n个圆盘全部移动到C柱子上,依然按照从上到下,从小到大的顺序排列。且对移动过程要求如下:

a)一次只能移动一个盘子。

b)移动过程中大盘子不允许出现在小盘子上方。

问:总共需要移动的步数是多少?

2 化繁为简,分析题目

从宏观角度来分析,将移动步骤分为三步:

a)将最上面的n-1个盘子移动到B柱子上

b)将最大的盘子移动到C柱子上

c)再将B柱子上的n-1个盘子移动到C柱子上

完成以上三步,即可达到目标。因此,问题转化为如何移动n-1个盘子?同样的思路解决n-1个盘子移动的问题,可以发现其中规律。假设移动n个盘子需要的步数为f(n),则移动n-1个判断需要f(n-1)步。

因此,得到递推公式:f(n) = 2 * f(n - 1) + 1

3 求解递推公式

将上一步的递推式进行变形:f(n) + 1 = 2(f(n - 1) + 1),设q(n) = f(n) + 1, 则q(n) = 2q(n-1), q(n) / q(n-1) = 2,可见q(n) 是一个等比序列,q(1) = 2,因此q(n) = 2^n(n >= 1), f(n) = 2^n - 1。

4 java编程实现递归算法

public class TowerOfHanoi 

    // 统计移动次数
    static int count = 0;

    public static void main(String[] args) 
        char a = A;
        char b = B;
        char c = C;
        int n = 3;
        TowerOfHanoi test = new TowerOfHanoi();
        test.recurse(n, a, b, c);
        System.out.println(count);
    

    // 移动一次
    private void move(int n, char from, char to)
        count = count + 1;
        System.out.println("将圆盘" + n + "号, 从" + from + "移动到" + to);
    

    // 递归
    private void recurse(int n, char a, char b, char c)
        // 递归结束条件:n == 1,只一个盘子时
        if (n == 1)
            move(1, a, c);
         else 
            recurse(n - 1, a, c, b);
            move(n, a, c);
            recurse(n - 1, b, a, c);
        
    

 

以上是关于汉诺塔问题的主要内容,如果未能解决你的问题,请参考以下文章

分治算法——汉诺塔问题

汉诺塔的C语言代码怎么写啊

汉若塔系列续:汉诺塔VIII汉诺塔IX汉诺塔X。

汉诺塔内存分析(python)

汉诺塔游戏规则

汉诺塔问题