zoukankan      html  css  js  c++  java
  • CodeVs[3145 汉诺塔游戏]

    题目描述 Description

    题目描述 Description

    汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题。在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔。

    游戏中的每一步规则如下:

    1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方)

    2. 移动的过程中,你必须保证大的盘子不能在小的盘子上方(小的可以放在大的上面,最大盘子下面不能有任何其他大小的盘子)

     

    如对于n=3的情况,一个合法的移动序列式:

    1 from A to C

    2 from A to B

    1 from C to B

    3 from A to C

    1 from B to A

    2 from B to C

    1 from A to C

     

    给出一个数n,求出最少步数的移动序列

    输入描述 Input Description

    一个整数n

    输出描述 Output Description

    第一行一个整数k,代表是最少的移动步数。

    接下来k行,每行一句话,N from X to Y,表示把N号盘从X柱移动到Y柱。X,Y属于{A,B,C}

    样例输入 Sample Input

    3

    样例输出 Sample Output

    7

    1 from A to C

    2 from A to B

    1 from C to B

    3 from A to C

    1 from B to A

    2 from B to C

    1 from A to C

    数据范围及提示 Data Size & Hint

    n<=10

     

    题解:

     

    在纸上画,发现基本规律:

    • 目标一定,最短路径有且只有一条。
    • 如果要把A中n个圆盘移动到C,必须把A中最下面的移动到C。要实现这一步,前一步必须是:A只剩最后一个元素,B中为A的前n-1个元素, C为空。

    百度百科:汉诺塔

    可以找到
    关于步数的函数:  1                       n =1

    f(n)

                  2 x f(n-1) - 1     n>=1

    (理解汉诺塔的递归原理后,很容易得到这样的结论):

     

    画图分析:

     

    最小递归:n=1,f(1)。

     

    n=2,实际是

    第一步:调用f(1)先将1移动 到B//基于发现的基本规律2.

    第二部:将A中最后一个元素移动到C,作为C的最里面的元素。

    第三部:此时,A为空,B为1,C为2。即又要调用f(1),只是这次B为源,C为目标,A作为临时储存器。

     

    n = 3,

    第一步:f(2),源为A,目标C

    第二步:将3从A移动到C。

    第三部:f(2),源为B,目标C

     

    n = n,

    第一步:f(n-1),源为A,目标C

    第二步:将n从A移动到C。

    第三部:f(n-1),源为B,目标C

     

    这样关于步数的函数显然易见。

     

    针对本题输出要求,用vector保存元素来输出。

     

    #include <iostream>
    #include <vector>
    #include <sstream>
    #include <string>
    #include <cmath>
    using namespace std;
    
    void remove(int n, vector<string> & src, vector<string> & mid, vector<string> & aim);
    int main(){
        vector<string> a,b,c;
        /*标示a、b、c塔。*/
    
        a.push_back("A");
        b.push_back("B");
        c.push_back("C");
        /////////
    
        int n;
        cin >> n;
        cout << pow(2, n) - 1 << endl;//输出最小步数
        
        /*填充塔A*/
        string str;
        ostringstream oss;
        for (int i = n; i > 0; i--)
        {
            oss.str("");
            oss << i;
            str = oss.str();
            a.push_back(str);
        }
        //////////////
    
        remove(n, a, b, c);
        return 0;
    }
    void remove(int n, vector<string> & src, vector<string> & mid, vector<string> & aim)//a 被移动者,b为储存器,c为目标。
    {
        if (n == 1){
            //此时a中只有一个元素1(不算名称a[0]),把他移动到aim
            string temp = src.back();
            src.pop_back();
            aim.push_back(temp);
            cout << 1 << " from " << src[0] << " to " << aim[0] << endl;
        }
        else {
    
            //将前n-1个元素 放到中间存储器中。
            remove(n - 1, src, aim, mid);
    
            //将src中最后一个元素 直接移到目标底部。
            string temp = src.back();
            src.pop_back();
            aim.push_back(temp);//把a的最后一个元素移动到c中。
            cout << temp << " from " << src[0] << " to " << aim[0] << endl;
    
            //再将中间存储器中的所有元素(有n-1)个全部移到 没有目标储存器中。
            remove(n - 1, mid, src, aim);
        }
    };

     

     

     

     

  • 相关阅读:
    Java基本数据类型
    java类和对象
    java命名规范
    算法(Algorithms)第4版 练习 1.5.16
    算法(Algorithms)第4版 练习 1.5.15
    算法(Algorithms)第4版 练习 1.5.14
    算法(Algorithms)第4版 练习 1.5.13
    算法(Algorithms)第4版 练习 1.5.12
    算法(Algorithms)第4版 练习 1.5.10
    算法(Algorithms)第4版 练习 1.5.9
  • 原文地址:https://www.cnblogs.com/dingblog/p/4454499.html
Copyright © 2011-2022 走看看