搜索:汉诺塔

先盗一张图:

正常的汉诺塔问题只要把A柱的所有盘子移动到C柱就好了,可以借助B柱。实现的逻辑如下:

void hanoi(int n,char a,char b,char c)
{
    ans++;
    if(n==1)
    {
        cout<<a<<"->"<<c<<endl; 
        return;
    }
    hanoi(n-1,a,c,b);
    cout<<a<<"->"<<c<<endl; 
    hanoi(n-1,b,a,c); 
}

我们在做这一类问题的时候如果从递归的终止条件去考虑的话,会容易很多。

我们就先看递归的终止条件

只剩一个盘子的时候,直接把A柱的盘子移动到C柱即可

否则,我们就要把A柱上的n-1个盘子从A柱借助于C柱移动到B柱

之后我们就可以顺理成章地把A柱上面剩下的最大的盘子移动到C柱了

最后我们需要把刚才移动到B柱上面的所有的盘子借助于A柱移动到C柱

我们只需要知道这个过程,具体的细节程序会帮着我们去做的

考虑问题的变式,只允许A和B之间,B和C之间发生盘子的移动。

下面先给出代码:

void hanoi2(int n,char a,char b,char c)
{
    ans+=2;
    if(n==1)
    {
        cout<<a<<"->"<<b<<endl; 
        cout<<b<<"->"<<c<<endl; 
        return;
    }
    hanoi2(n-1,a,b,c);
    cout<<a<<"->"<<b<<endl; 
    hanoi2(n-1,c,b,a);
    cout<<b<<"->"<<c<<endl; 
    hanoi2(n-1,a,b,c);  
}

我们同样先考虑只有一个盘子的情况,很显然是A->B,然后B->C

否则,我们需要递归完成如下操作

先把A上面的n-1个盘子经过B柱移动到C柱(这是一个递归的过程,不要在这里产生疑问,因为递归的过程中问题会分解)

这时候A上面只剩一个大盘子了,我们顺理成章地将其移动到B柱

然后我们要做的是把C柱上面的n-1个盘子经由B柱移动到A柱,这是为啥呢?是为了给刚才放在B柱上面的那个大盘子腾地方。

腾完了地方,就可以把刚才放在B柱上面的那个大盘子顺理成章地移动到C柱

最后再递归处理子过程,把A上的n-1个盘子经由B柱移动到C柱。

我们总结一下一共需要多少步,第一种情况需要2^n-1,第二种情况需要3^n-2,具体为什么可以根据递归函数的特点得知。

总的程序如下:

 1 #include<iostream>
 2 using namespace std;
 3 int ans=0;
 4 void hanoi(int n,char a,char b,char c)
 5 {
 6     ans++;
 7     if(n==1)
 8     {
 9         cout<<a<<"->"<<c<<endl; 
10         return;
11     }
12     hanoi(n-1,a,c,b);
13     cout<<a<<"->"<<c<<endl; 
14     hanoi(n-1,b,a,c); 
15 }
16 void hanoi2(int n,char a,char b,char c)
17 {
18     ans+=2;
19     if(n==1)
20     {
21         cout<<a<<"->"<<b<<endl; 
22         cout<<b<<"->"<<c<<endl; 
23         return;
24     }
25     hanoi2(n-1,a,b,c);
26     cout<<a<<"->"<<b<<endl; 
27     hanoi2(n-1,c,b,a);
28     cout<<b<<"->"<<c<<endl; 
29     hanoi2(n-1,a,b,c);  
30 }
31 int main()
32 {
33     int n;
34     cin>>n;
35     hanoi2(n,'A','B','C');
36     cout<<ans<<endl;
37     return 0;
38 }

 

posted @ 2018-07-07 19:10  静听风吟。  阅读(290)  评论(0编辑  收藏  举报