一道汉诺塔的变形题

题目描述


糖和抖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;
}

实不相瞒,我一开始就是直接找规律做的,反而是递归的方法花了很久才理解......(我这奇奇怪怪的脑回路啊......)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值