• 理解 Hanoi 汉诺塔非递归算法


    汉诺塔介绍:

    汉诺塔(港台:河内塔)是根据一个传说形成的数学问题:

    最早发明这个问题的人是法国数学家爱德华·卢卡斯

    传说越南河内某间寺院有三根银棒,上串 64 个金盘。寺院里的僧侣依照一个古老的预言,以上述规则移动这些盘子;预言说当这些盘子移动完毕,世界就会灭亡。这个传说叫做梵天寺之塔问题(Tower of Brahma puzzle)。但不知道是卢卡斯自创的这个传说,还是他受他人启发。

    若传说属实,僧侣们需要 (2^{64}-1)步才能完成这个任务;若他们每秒可完成一个盘子的移动,就需要5849 亿年才能完成。整个宇宙现在也不过 137 亿年

    这个传说有若干变体:寺院换成修道院、僧侣换成修士等等。寺院的地点众说纷纭,其中一说是位于越南河内,所以被命名为“河内塔”。另外亦有“金盘是创世时所造”、“僧侣们每天移动一盘”之类的背景设定。

    介绍完汉诺塔背景以后开始解决下非递归思路

    汉诺塔的非递归算法描述如下:

    首先容易证明,当盘子的个数为n时,

    假设有 n 片,移动最少次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。

    此后不难证明 n 片时移动的次数应等于2(^n - 1)

    一位美国学者发现一种出人意料的方法,只要轮流进行两步操作就可以了。

    我们假设现在最小的圆盘在a柱子上,柱子为a,b,c

    第一步:将最小圆盘移动到下一个柱子上,也就是b

    第二步:对a柱子和c柱子进行顶上最小的元素进行判断,把小一点的那个圆盘移动到大一点的那个圆盘(有空则摞在空柱子上)。

    反复进行前面两步操作,最后就能按规定完成汉诺塔的移动。

    注意:这样得到的最后的答案不一定是摞在c上,如果N是偶数将摞在b上,所以如果N是偶数我们就令第二个柱子为c,第三个柱子为b,这样就一定最后是摞在c上的。

    汉诺塔非递归算法实现

    #include<iostream>
    #include<stack>
    using namespace std;
    char s[3] = { 'a', 'b', 'c' };//代表3个柱子
    stack<int> a[3];
    bool move(int before, int after)
    {
        if (a[before].empty())
            return false;
        if (!a[after].empty()){
            if (a[after].top() - a[before].top() < 0)
                return 0;
        }
        a[after].push(a[before].top());
        a[before].pop();
        printf("%c -> %c
    ", s[before], s[after]);
        return true;
    }
    int main()
    {
        int N, count = 0;
        cin >> N;
        for (int i = 0; i < N; i++)
            a[0].push(N - i);
        if (N % 2 == 1)
        {
            s[1] = 'c';
            s[2] = 'b';
        }
        while (++count){
            move((count - 1) % 3, count % 3);
            if (!move((count - 1) % 3, (count + 1) % 3))
            if (!move((count + 1) % 3, (count - 1) % 3))
                break;
        }
        return 0;
    }
    

    题目实战链接 PTA7-17

    查找资料的时候发现N皇后问题与汉诺塔的非递归有类似又不同的思想,这几天赶快安排下学习N皇后(偷懒好久了2333)

  • 相关阅读:
    Django连接MySQL(二)
    Django框架,python2和python3共存的情况下,创建Django项目
    pycharm破解
    dbutils中实现数据的增删改查的方法,反射常用的方法,绝对路径的写法(杂记)
    Spring中的事物管理,基于spring的bean的配置
    Spring中的事物管理,用 @Transactional 注解声明式地管理事务
    Ajax中GET和POST的区别
    Spring对 JDBC 的支持,JdbcTemplate类的使用
    Spring AOP:面向切面编程,AspectJ,是基于spring 的xml文件的方法
    Spring AOP:面向切面编程,AspectJ,是基于注解的方法
  • 原文地址:https://www.cnblogs.com/RioTian/p/12684372.html
Copyright © 2020-2023  润新知