• 递归一个十分magic的思想


    汉诺塔问题

    次数问题

    #include <iostream>
    
    using namespace std;
    
    
    /*
        将n个盘子从x搬到z 可以转化为  先n上方n-1个盘子搬到y,再把n这个盘子搬到z,最后将n-1个盘子从y搬到z。依次类推。
        即f(n) 的问题可以转化为f(n-1)的问题,...,f(1);
    
        三根柱子 分别用 x y z 表示
        伪代码如下:
        int fz(int n)
        {
            if(n == 1) return 1;
            else
                return fy(n-1) + 1 + fz(n-1);
        }
    */
    unsigned long long f(int n)
    {
        if (n == 1) return 1;
        else
            return 2 * f(n - 1) + 1;
    }
    
    int main() {
    
        // test 
        cout << "step cnt " << f(3) << endl;  // 3个盘子  从0搬运到2
        cout << "step cnt " << f(4) << endl;  // 4个盘子  从0搬运到2
        cout << "step cnt " << f(64) << endl; // 64个盘子 从0搬运到2
        /*
        step cnt 7
        step cnt 15
        step cnt 18446744073709551615  // 这个数字超过了long long 的范围,这里用unsigned long long
        */
    
    }

    64个金盘,如果每秒移动一个,那么按照它的这个规则需要5849亿年。

    搬运步骤问题

    我们假设搬运n个盘子,且他们的序号为1-n。三个柱子的索引为0,1,2。

    使用(plateNo,fromIdx,toIdx) 三个数的元组来表示每一次搬运的过程。有了这个数据结构,我们也可以用代码可视化的展示汉诺塔的搬运过程。

    则有如下递归程序来描述搬运过程

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    
    void f(int n,int fromIdx,int toIdx,vector<vector<int>>& vvRet)
    {
        if(n == 1)
            vvRet.push_back({1,fromIdx,toIdx});
        else
        {
            f(n-1,fromIdx,3-fromIdx-toIdx,vvRet);
            vvRet.push_back({n,fromIdx,toIdx});
            f(n-1,3-fromIdx-toIdx,toIdx,vvRet);
        }
    }
    
    
    int main() {
        
        // test 
        vector<vector<int>> vvRet;
        //f(3,0,2,vvRet);  // 3个盘子 从0搬运到2
        /*
        ( 1, 0, 2 )
        ( 2, 0, 1 )
        ( 1, 2, 1 )
        ( 3, 0, 2 )
        ( 1, 1, 0 )
        ( 2, 1, 2 )
        ( 1, 0, 2 )
        */
        f(4,0,2,vvRet);  // 4个盘子 从0搬运到2
        /*
        ( 1, 0, 1 )
        ( 2, 0, 2 )
        ( 1, 1, 2 )
        ( 3, 0, 1 )
        ( 1, 2, 0 )
        ( 2, 2, 1 )
        ( 1, 0, 1 )
        ( 4, 0, 2 )
        ( 1, 1, 2 )
        ( 2, 1, 0 )
        ( 1, 2, 0 )
        ( 3, 1, 2 )
        ( 1, 0, 1 )
        ( 2, 0, 2 )
        ( 1, 1, 2 )
        */
        for(auto item:vvRet)
        {
            cout << "( "<<item[0]<<", "<<item[1]<<", "<<item[2]<<" )"<<endl;
        }
    
    }
  • 相关阅读:
    raspbian设置locale
    docker redis
    consul开发部署集群
    自动更新ssh登录的key到远程主机
    docker官方脚本阿里云镜像
    nodejs中国镜像
    github修改hosts加速
    docker容器更新总是自动重启
    webstrom不显示右边的竖线,代码结构线
    _mssql.c:266:22: fatal error: sqlfront.h: No such file or directory
  • 原文地址:https://www.cnblogs.com/zach0812/p/16218604.html
Copyright © 2020-2023  润新知