汉诺塔问题的C++实现

来源:互联网 发布:知乎怎么按点赞数排序 编辑:程序博客网 时间:2024/05/22 04:34
汉诺塔问题的C++实现


#include<iostream>
using namespace std;


char A,B,C;


int main()
{
    int n;
    void hano(int,char,char,char);
    cout<<"请输入A座上的盘子数目:";
    cin>>n;
    hano(n,'A','B','C');
    return 0;
}






void print(char A,char C)
{
     cout<<A<<"--"<<C<<endl;
}




void hanoi(int n,char A,char B,char C)
{
    if(n==1) 
print(A,C);
    else
    {
          hanoi(n-1,A,C,B);
          print(A,C);
          hanoi(n-1,B,A,C);
    }
}




说明:


   规模为n的汉诺塔问题可以写成两个规模为n-1的汉诺塔问题的和。也就是说若用H(n)表示规模为n的汉诺塔问题的解的话,则H(n)= 2H(n-1)+1。最后加的1就是printf("%d->%d\n",a,c);的含义。
    
    以上就是汉诺塔问题的数学模型,比较抽象。
    就以Hanoi(4,1,2,3)举例来说:1、2、3分别代表可以存放盘子的底座的编号,4表示刚开始时第1个底座有4个盘子,a、b、c分别代表:问题开始时的原来存放盘子的底座、临时底座、问题结束时盘子存放的底座。那么怎么将第1个底座上4个盘子移动到第3个底座上呢?
    按照上面的模型,分成三步:
    (1)将第1个底座的最上面的3个盘子移动到第2个底座上;
    (2)将第1个底座上剩下的1个盘子直接放到第3个底座上;
    (3)将第2个底座上的3个盘子移动到第三个底座上;
    上面三个过程实际上就对应到你的Hanoi(...)函数的中的三个语句。
第(1)、(3)步就是相当于原来问题的两个变形。可以把第(1)步理解为:将n-1个盘子从第1个底座搬到第2个底座的汉诺塔问题,这样问题有3个变化的地方和1个不变的地方:盘子总数减少了1、要将盘子移动到的目标底座变成了第2个底座了、临时底座变成了第3个底座了、问题的本质上还是汉诺塔问题,这个不变很重要,它是问题可以递归求解的关键,也就是说可以用不同的参数来调用同一个函数来解决。对应到Hanoi(...)函数的4个参数中的3个变化。
    完成了前面两步后,显然问题并没有解决,所以才有第(3)步,也就是第二个递归。同样的道理第(3)步可以理解为:将n-1个盘子从第2个底座搬到第三个底座的汉诺塔问题了。只不过与第一个递归不同的是:原来的第2个底座相当于原来的第1个底座、原来的第1个底座相当于现在的第2个底座了。
    
补充:对于初学者来说,求解汉诺塔问题的方法其实很简单,但是求解的细节却很绕人,1、2、3与a、b、c的关系就不太好理解。个人认为搞清楚形式参数与实际参数的关系会对理解程序代码有帮助。直观的来看,123就是实际参数,abc就是形式参数。由前面内容可以看出,其实123和abc的意义在每一层递归调用中的含义是不同的,但就Hanoi(int n,int a,int b,int c)而言,每次调用它都是把当前要移动的盘子总数传给n、盘子初始位置传给a、目标位置传给c。进入Hanoi函数内部以后,问题被分解为“三步走”这样abc的具体含义在递归调用时就变化了。
原创粉丝点击