-
题目描述:
-
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?
-
输入:
-
包含多组数据,每次输入一个N值(1<=N=35)。
-
输出:
-
对于每组数据,输出移动最小的次数。
-
样例输入:
-
1 3 12
-
样例输出:
-
2 26 531440
-
思路:
-
其实递归问题重在思路,以下内容摘自《2013年王道论坛计算机考研机试指南》:
-
为了首先将初始时最底下、最大的圆盘移动到第三根柱子上,我们首先需要将其上的 K-1 个圆盘移动到第三根柱子上,而这恰好等价于移动 K-1 个圆盘从第一根柱子到第三根柱子。当这一移动完成以后,第一根柱子仅剩余最大的圆盘,第二根柱子为空,第三根柱子按顺序摆放着 K-1 个圆盘。我们将最大的圆盘移动到此时没有任何圆盘的第二根柱子上,并再次将 K-1 个圆盘从第三根柱子移动到第二根柱子,此时仍然需要移动K-1 个圆盘从第一根柱子到第三根柱子所需的移动次数(第一根柱子和第三根柱子等价),当这一移动完成以后将最大的圆盘移动到第三根柱子上,最后将 K-1个圆盘从第一根柱子移动到第三根柱子上。若移动 K 个圆盘从第一根柱子到第三根柱子需要 F[K]次移动,那么综上所述 F[K]的组成方式为,先移动 K-1 个圆盘到第三根柱子需要 F[K-1]次移动,再将最大的圆盘移动到中间柱子需要 1 次移动,然后将 K-1 个圆盘移动回第一根柱子同样需要 F[K-1]次移动,移动最大的盘子到第三根柱子需要 1 次移动,最后将 K-1 个圆盘也移动到第三根圆盘需要F[K-1]次移动,这样 F[K] = 3 * F[K - 1] + 2。即从第一根柱子移动 K 个圆盘到第三根柱子,需要三次从第一根柱子移动 K-1 个圆盘到第三根柱子,外加三次对最大圆盘的移动。若函数 F(x)返回移动 x 根子所需要的移动次数,那么其递归方式为 3*F(x-1) + 2。
-
代码:
-
#include <iostream> using namespace std; int step=0; void move(char x,char y,int n) { if(n>1) { move('a','c',n-1); move('a','b',1); move('c','a',n-1); move('b','c',1); move('a','c',n-1); } else { if(abs(x-y)==1) { cout<<x<<"->"<<y<<"\n"; ++step; } else { cout<<x<<"->b->"<<y<<endl; step+=2; } } } long long f(int n) { if(n==1) return 2; else return 3*f(n-1)+2; } int main() { int n; while(cin>>n) { long long step=0; for(int i=1;i<=n;++i) { step=3*step+2; } cout<<step<<endl; } return 0; }