题目描述
糖和抖m在玩个游戏,规定谁输了就要请谁吃顿大餐:抖m给糖a b c三个驻, 并在a柱上放置了数量为n的圆盘,圆盘的大小从上到下依次增大,现在要做的事就是把a柱的圆盘全部移到c柱,移动的过程中保持小盘在上,大盘在下,且限定圆盘只能够移动到相邻的柱子,即a柱子上的圆盘只能够移动到b,b柱子上的圆盘只能够移动到a或者c,c同理。现在请你设计一个程序,计算所需移动的最小步数, 帮助糖赢得大餐!
输入描述:
每一行输出有一个整数n(0<=n<26), 直至文件末尾。
输出描述:
对于每一组数据,输出一行,输出移动的最小步数M。
样例1:
输入:
1
输出:
2
解题思路:递归。
举几个例子:n=1时,我们需要把圆盘先从a柱移动到b柱,再从b柱移动到c柱,一共需要移动两步。n=2时,我们先把上面那个小圆盘从a柱移动到c柱,根据n=1时的结论可知为2步;此时再将大圆盘从a柱移动到b柱,步数+1;再将小圆盘从c柱移动到a柱,步数+2;再将b柱的大圆盘移动到c柱,步数+1;最后将小圆盘从a柱移动到c柱,步数+2,总共步数为8步。n=3时,以此类推。
我们可以发现,每次都是先将n-1个圆盘从a柱移动到c柱,b柱为缓冲区;再将第n个圆盘从a移动到b,步数+1;再将n-1个圆盘从c移动到a,b柱为缓冲区;再将第n个圆盘从b移动到a,步数+1;最后将n-1个圆盘从a移动到c,完成移动。而这n-1个圆盘移动的步数也满足这个规律,因此可以写出如下的代码:
#include<iostream>
using namespace std;
int sum=0;
void move(int from,int buffer,int to,int n){
if(n>0){
move(from,buffer,to,n-1);//从a移动到c,b为缓冲区
sum++;
move(to,buffer,from,n-1);//从c移动到a,b为缓冲区
sum++;
move(from,buffer,to,n-1);//从a移动到c,b为缓冲区
}
}
int main(){
int n;
while(cin>>n){
sum=0;//移动步数
move(1,2,3,n);//分别代表a柱、b柱、c柱和圆盘数量
cout<<sum<<endl;
}
return 0;
}
当然,from、buffer和to只是用来辅助理解,不写进递归里也没关系,毕竟重点是对n做递归嘛。
除了递归的做法以外,还可以直接找规律。代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int n,i;
while(cin>>n){
int sum=0;
for(i=0;i<n;i++){
sum+=pow(3,i);
}
cout<<sum*2<<endl;
}
return 0;
}
实不相瞒,我一开始就是直接找规律做的,反而是递归的方法花了很久才理解......(我这奇奇怪怪的脑回路啊......)