算法分析:
对于这个问题,我们不纠结于每一小步,我们先把问题抽象出来。A上的盘子最后都要移到C上,那么必须借助B,最根本的一步是将最大的4号盘子移到C上,将1~3号盘子移到B上(这里我们将所有的分成两个部分,第一部分是最大盘子,第二部分是除了最大盘子外的所有盘子),这个问题就简化成了将第一部分移到C,第二部分移到B,再将第二部分移到C,就实现了目的。也就是将问题抽象成以下三个步骤。
(1)将A上的3个盘子借助C移到B
(2)将A上的最大的盘子移到C
(3)将B上的3个盘子借助A移到C
这三个步骤可以用函数抽象出来,其中(1)和(3)可以使用一个函数。刚才所说的是分成两大部分,怎么样才能细化到每一步呢?就是使用函数的递归,找到最基础的一步,通俗的讲,函数递归就是将该做的同类事情先整合到一起,最后不断调用细化到每步里(例如斐波那契数列),从最大的一步开始寻找最基础的一步,然后返回向上寻找每一步的结果。
一般来说,有n个盘子的汉诺塔,就可以抽象出来三个步骤:
(1)将A上的n-1个盘子借助C移到B
(2)将A上的最大的盘子移到C
(3)将B上的n-1个盘子借助A移到C
每个抽象出来的函数参数都可以得到了。
C:
#include<stdio.h>
int i=0;
void move(char x,char y)
{
printf("(Step%d):%c->%c\n",++i,x,y);
}
void hanoi(int n,char one,char two,char three)
{
if(n==1)move(one,three); //如果盘子个数为一个,直接从'A'移到'C'
else //如果盘子个数大于一个
{
hanoi(n-1,one,three,two); //'A'上的n-1个盘子借助'C'移到'B'
move(one,three); //把'A'上的盘子移到'C'
hanoi(n-1,two,one,three); //'B'上的n-1个盘子借助'A'移到'C'
}
}
int main()
{
int m;
printf("输入汉诺塔的盘子个数:");
scanf("%d",&m);
hanoi(m,'A','B','C');
printf("共需要%d步",i);
return 0;
}
C++:
#include<iostream>
using namespace std;
int i=0;
void move(char x,char y)
{
cout<<"(Step"<<++i<<"):"<<x<<"->"<<y<<endl;
}
void hanoi(int n,char one,char two,char three)
{
if(n==1)move(one,three); //如果盘子个数为一个,直接从'A'移到'C'
else //如果盘子个数大于一个
{
hanoi(n-1,one,three,two); //'A'上的n-1个盘子借助'C'移到'B'
move(one,three); //把'A'上的盘子移到'C'
hanoi(n-1,two,one,three); //'B'上的n-1个盘子借助'A'移到'C'
}
}
int main()
{
int m;
cout<<"输入汉诺塔的盘子个数:";
cin>>m;
hanoi(m,'A','B','C');
cout<<"共需要"<<i<<"步";
return 0;
}