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);
    }
};
时间: 2024-08-04 11:59:35

CodeVs[3145 汉诺塔游戏]的相关文章

3145 汉诺塔游戏——http://codevs.cn/problem/3145/

第一部分:题目 题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔. 游戏中的每一步规则如下: 1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方) 2. 移动的过程中,你必须保证大的盘子不能在小的盘子上方(小的可以放在大的上面,最大盘子下面不能有任何其他大小的盘子) 如对于n

3145 汉诺塔游戏

题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔. 游戏中的每一步规则如下: 1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方) 2. 移动的过程中,你必须保证大的盘子不能在小的盘子上方(小的可以放在大的上面,最大盘子下面不能有任何其他大小的盘子) 如对于n=3的情况,一个

codevs 3145 汉诺塔

#include<cstdio> #include<cmath> #include<cctype> #include<iostream> #include<vector> #include<cstring> #include<algorithm> #include<map> #include<set> #include<cstddef> #include<sstream> #

codevs3145 汉诺塔游戏

3145 汉诺塔游戏 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 白银 Silver 题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔. 游戏中的每一步规则如下: 1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方) 2. 移动的过程中,你必须保证大的盘子

Pyhton:汉诺塔游戏

#汉诺塔游戏攻略! def hanoi(n,x,y,z): if n == 1: print(x,'-->',z) else: hanoi(n-1,x,z,y) #将前n-1个盘子从x移动到y上 print(x,'-->',z) #将最底下的最后一个盘子从x移动到z上 hanoi(n-1,y,x,z) #将y上的n-1个盘子移动到z上 n = int(input('请输入层数:')) hanoi(n,'x','y','z') 输出结果为: 请输入层数:3 x --> z x -->

经典分治 - 汉诺塔游戏

分治策略: 将父问题划分为多个子问题(注:子问题与父问题一定要具有自相似性),然后找递归出口. 1.子问题规模变小.2.子问题与父问题本质等价. 汉诺塔游戏简述:三个柱A.B.C,将从大到小的盘按规则从A柱移到B柱. 具体的分治算法实现: 1 - N从A移动到B,C为辅助. 等价于: 1.1 - (N - 1)从A移动到C,B为辅助 2.把N从A移动到B 3.1 - (N - 1)从C移动到B,A为辅助 话说当时刚开始想这个问题的时候,我把2 - N当作一个子问题移动对象,将1盘移到辅助柱子上,

Unity实现汉诺塔游戏

汉诺塔的规则: 有ABC三个柱子,A柱子上从小到大排列圆盘 要将A柱子上所有圆盘移动到C柱子上,每次只能移一个 圆盘放置必须从小到大,不能存在此盘子上面有比它大的存在. 比如三个汉诺塔玩法: 理理思路,大体算法就是这个样: 那么算法就很清晰了. 不知道哪一天我又想把这个游戏扩展,我决定用四个类,让游戏的设计更条理一点: Temp类//临时存储圆盘对象,就是正在移动的圆盘 Torus类//圆盘类,每个圆盘都有 Cylinder类//圆柱类,每个圆柱都用,鼠标点击触发游戏 GameManage类//

codevs3145 汉诺塔游戏(经典中的经典,不能再经典了)

题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔. 游戏中的每一步规则如下: 1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方) 2. 移动的过程中,你必须保证大的盘子不能在小的盘子上方(小的可以放在大的上面,最大盘子下面不能有任何其他大小的盘子) 如对于n=3的情况,一个

wiki 3145 汉诺塔的输出过程

题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一开始他们都叠在我A上(如图所示),你的目标是在最少的合法移动步数内将所有盘子从A塔移动到C塔. 游戏中的每一步规则如下: 1. 每一步只允许移动一个盘子(从一根柱子最上方到另一个柱子的最上方) 2. 移动的过程中,你必须保证大的盘子不能在小的盘子上方(小的可以放在大的上面,最大盘子下面不能有任何其他大小的盘子) 如对于n=3的情况,一个