汉诺塔问题

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。

大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个,金刚石和黄金都以木头代替了......但道理是相同的。

据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日!

你的任务是精确计算出到底需要移动多少次。

很明显,如果只有2个圆盘,需要移动3次。

圆盘数为3,则需要移动7次。

那么64个呢?

答案写在“解答.txt”中,不要写在这里!

图1

 

参考答案:

18446744073709551615


找了很多解释,下面的是我觉得最好的一种,茅塞顿开

汉诺塔这个问题,在考虑它递归的时候,别想着我们真实移动的步骤,我当时也总是觉得很乱。你要这样考虑:
1, 2, 3
最初都在1上,最后要移动到3上。所以把除了最后一块都移动到2上,最后一块移动到3上,再把2的都移动到3上。这个过程就结束了。
那怎么把东西都移动到2上呢,你假设,2在3的位置,1还是1, 3在2的位置,这样顺序变成了:
1, 3, 2。
问题就变成了如何把1上的都移动到2上,道理还是一样,就是,把除了最后一块的所有块都移动到3上,把最后一块移动到2上,再把3上面的所有块移动到2上。
这样就能抽象出一个过程:
1.移动多块到2的位置上. //hanoi(n-1,one,three,two);n-1块,从1到2,只看第2个和第4个参数,one,two就是从1到2.
2.移动一块到到3的位置上. //move(one,three);
3.移动在2的位置上的多块到3的位置上. //hanoi(n-1,two,one,three);n-1块,从2到3,只看第2个和第4个参数,two,three就是从2到3.

递归都有一个最终结束的条件,这里就是n=1的时候,也就是只有一个汉诺塔块的时候,只有一个的时候,肯定是从1直接移动到3了。

抽象成函数,就是
void hanoi(int n,char one ,char two,char three)

{
  if(n==1) move(one,three);  

       else 

    { 

            hanoi(n-1,one,three,two);  

              move(one,three); 

           hanoi(n-1,two,one,three); 

    }
}

void move(char x,char y)
{  printf("%c-->%c\n",x,y);}

计算顺序:

#include <iostream>

using namespace std;

/**
*汉诺塔问题: 将 A 上所有的盘子,移动到 C 上 ,A B C
*/
void moveAC(char A,char C)
{
    cout<<A<<"->"<<C<<endl;
}
void recursion_hano(int n,char A,char B,char C)
{
    //递归的终止条件
    if(n==1)
    {
        moveAC(A,C);
        return;
    }
    //先将 A 上上边n-1个盘子移动到 B上
    recursion_hano(n-1,A,C,B);  // 将 A 上 n-1 个圆盘移动到 B上
    moveAC(A,C);    //将最大的圆盘移动到 C上
    recursion_hano(n-1,B,A,C);  //将B上的圆盘移动到C上	
}
int main()
{
    cout << "Hello world!" << endl;
    recursion_hano(4,'A','B','C');
    return 0;
}


计算步骤:

#include <iostream>
#include <stdio.h>
using namespace std;

static int step = 0;
void move ( char sour, char dest )
{
    printf ( "move from %c to %c \n", sour, dest );
}

void hanoi ( int n, char sour, char temp, char dest )
{
    if ( n == 1 )
    {
        move ( sour, dest );
        ++step;
    }
    else
    {
        hanoi ( n-1, sour, dest, temp );
        move ( sour,dest );
        ++step;
        hanoi ( n-1, temp, sour, dest );
    }
}
int main ( int argc, char **argv )
{
    int n = 4;
    hanoi ( n, 'A', 'B', 'C' );
    printf ( "Total steps is %d\n", step );
    return 0;
}


### 回答1: 这段英文描述的是汉诺塔问题,它是一个经典的问题。汉诺塔(Hanoi Tower)又称河内塔,源于印度的一个古老传说。大梵天创造世界时造了三根金刚石柱子,在一根柱子上从下往上按大小顺序放着64片黄金圆盘,大梵天命令婆罗门把圆盘从下面开始按大小顺序依次移到另一根柱子上,且过程中小圆盘必须在大圆盘上面,不允许大圆盘压在小圆盘上面。完成这项任务所需的步数是2的64次方减1,约等于18.4亿步,如果每秒钟完成一步,需要585年左右。 ### 回答2: 婆将这些圆盘从一根柱子上全部移到另一根柱子上,并且规定只能借助第三根柱子。根据传说,当婆婆完成这个任务时,世界就将结束。这个问题看似简单,但是实际上需要一定的推理和图形思维。解决这个问题的难点在于如何将大盘从一根柱子移到另一根柱子,并且保证每个圆盘的大小关系不变,即大盘不能压在小盘上面。最简单的方法就是逐个移动,但是这需要大量的次数和时间。数学家提出的递归思想则更加高效,将问题化简为递归子问题进行解决。在汉诺塔问题中,每个盘子都可以看做一个节点,将问题转化为移动一个子问题,然后再移动根节点,最后再将子问题移动回去。这样,每次只需移动一个盘子,且规律逐渐显现出来,即移动n个盘子的方法可以转化为移动n-1个盘子+移动根节点+移动n-1个盘子的方法,从而避免了重复计算和无限递归。因此,汉诺塔问题不仅锻炼了我们的思维逻辑和数学能力,还展示了递归方法在计算中的实际应用。 ### 回答3: 罗门把这些盘子从下面开始按照大小顺序移到另外一根柱子上。 汉诺塔问题是指有三根柱子和一堆不同大小的盘子,盘子从下往上按照逐渐变大的顺序摆放在一根柱子上。游戏的目标是把所有盘子都移动到另一根柱子上,每次只能移动一个盘子,且大盘子不能放在小盘子之上。 这个经典问题涉及到递归、分治和数学方面的知识。在解决汉诺塔问题时,使用递归可以简化问题,并找到一种通用的解决方法。通过分治思想,将复杂问题分解成小问题来解决,使得问题变得更加容易处理。 在计算汉诺塔问题中,我们可以使用数学公式来计算出移动盘子的最小步骤数。对于一个汉诺塔问题,最少的步骤数可以计算为2的n次方减一,其中n为盘子的数量。 汉诺塔问题是一个非常有趣的问题,它不仅可以用来锻炼我们的思维能力,还能帮助我们理解递归和分治思想,同时也为我们提供了一个优秀的数学智力游戏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值