• 汉诺塔问题


    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);
            }
        }
    }
  • 相关阅读:
    Android学习小Demo(20)关于Fragment的应用
    计算机常识--框架、编程语言篇
    用python做oj上的简单题(持续更新中.......)
    UIControl-IOS开发
    Android各种屏幕分辨率(VGA、HVGA、QVGA、WQVGA、WVGA、FWVGA) 具体解释
    包管理器Bower使用手冊之中的一个
    23web app实现上下左右滑动
    iOS IAP教程
    一步一步写算法(之 A*算法)
    执行游戏时出现0xc000007b错误的解决方法
  • 原文地址:https://www.cnblogs.com/mydesky2012/p/11514302.html
Copyright © 2020-2023  润新知