汉诺塔问题

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

大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值