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

Posted 就是干不掉我

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3145 汉诺塔游戏——http://codevs.cn/problem/3145/相关的知识,希望对你有一定的参考价值。

第一部分:题目

题目描述 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->C,只需要一步:1 from A to C.把2个盘子从A->C:要先把2从A->B,然后把1从A->C,最后把2从B->C;规律就是:当N>1时,先把N-1个上面的盘子移到目标柱子的另外一个柱子(这里称为 伪目标柱子),然后把N从当前柱子移到目标柱子,最后把N-1个盘子从伪目标柱子移到目标柱子。从这里可以得出,最少步骤等于2的n次方减1.

第三部分:代码

#include<stdio.h>
void show(int n,char now,char target)//now 表示当前盘子所在柱子,target表示目标柱子
{
    if(n==1)//如果当前只需要把1个盘子从now 移到target,那么就直接移过去
    {
        printf("%d from %c to %c\n",n,now,target);
    }
    else   
    {
        if(target==C)//当有多个盘子时,需要先把上面n-1个盘子先移到除now 和target外的第三个柱子,这里称之为伪目标柱子,可想而知,伪目标柱子是未知的,需要进行判断
        {
            if(now==A)
            {
                show(n-1,now,B);//把n-1个上面的盘子移到伪目标柱子
                printf("%d from %c to %c\n",n,now,target);//把n号盘子移到目标柱子
                show(n-1,B,target);//把n-1个上面的盘子移到目标柱子,“此处一定要注意,不要丢了”。下面是其他情况,原理一样
            }
            else
            {
                show(n-1,now,A);
                printf("%d from %c to %c\n",n,now,target);
                show(n-1,A,target);
            }
        }
        if(target==B)
        {
            if(now==A)
            {
                show(n-1,now,C);
                printf("%d from %c to %c\n",n,now,target);
                show(n-1,C,target);
            }
            else
            {
                show(n-1,now,A);
                printf("%d from %c to %c\n",n,now,target);
                show(n-1,A,target);
            }
        }
        if(target==A)
        {
            if(now==B)
            {
                show(n-1,now,C);
                printf("%d from %c to %c\n",n,now,target);
                show(n-1,C,target);
            }
            else
            {
                show(n-1,now,B);
                printf("%d from %c to %c\n",n,now,target);
                show(n-1,B,target);
            }
        }
    }
}
int main()
{
    int n,sum=1,i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)//根据规律得出最少步骤是2的n次方减1
    {
        sum*=2;
    }
    sum--;
    printf("%d\n",sum);
    show(n,A,C);//n个盘子要从柱子A移到柱子B
    return 0;
}

 

 

以上是关于3145 汉诺塔游戏——http://codevs.cn/problem/3145/的主要内容,如果未能解决你的问题,请参考以下文章

codevs3145 汉诺塔游戏

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

codevs3145 汉诺塔问题

汉诺塔游戏规则

河内塔游戏

汉诺塔游戏