• 理解 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)

  • 相关阅读:
    spark internal
    74LS153 选择器 【数字电路】
    Linux(centos)下mysql编译安装教程
    Android画布更新过程OnDraw调用过程
    Android中使用ContentProvider进行跨进程方法调用
    hdu5414(2015多校10)--CRB and String(字符串匹配)
    徒弟们对话,遇到sb领导,离职吧
    【Cocos2d-x 017】 多分辨率适配全然解析
    编程精粹--编写高质量C语言代码(4):为子系统设防(一)
    为SSD编程(4)——高级功能和内部并行
  • 原文地址:https://www.cnblogs.com/RioTian/p/12684372.html
Copyright © 2020-2023  润新知