HDU2077 汉诺塔IV
原题链接在此:HDU2077
这道题目会用到HDU2064汉诺塔III的递推式,可以参考我的另一篇博客:汉诺塔III。
本问题和III的区别在于最后一个圆盘,但恰恰因为最后一个圆盘,之前的思路需要大的改动(因为我们不知道最后一块圆盘到底是第几块)。
假设变量:
- 设a[i]为将第i块圆盘从左边移动到右边(或从右到左)的步数;
- b[i]为将第i块圆盘从左边移动到中间(或从右到中间,或从中间到左、右)的步数;
- c[i]为如果i为最后一个圆盘,一共所需要的步数
分析思路如下:
- 将前 n-1 个圆盘移动到中间柱子上
- 把第 n个盘子移到中间再移到右边
- 最后把中间 n-1个圆盘移到右边
以上三行总结的公式:c[n]=2*b[n-1]+2 ;
现在我们需要求b[i]:
- 先把前i-1个从左边移到右边
- 再把第i个圆盘移到中间
- 最后把前i-1个从右边移到中间
以上总结出的公式为:b[i]=a[i-1]+b[i-1]+1;
现在我们需要求a[i],而求a[i]的方式在汉诺塔III的博客里面,不再赘述。
实现代码
#include<cstdio>
using namespace std;
int main(){
int n,i,t;
long long a[20],b[20],c[20];
a[0]=2;b[0]=1;c[0]=2;
for(i=1;i<20;i++){
a[i]=3*a[i-1]+2;
}
for(i=1;i<20;i++){
b[i]=a[i-1]+b[i-1]+1;
}
for(i=1;i<20;i++){
c[i]=2*b[i-1]+2;
}
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%lld\n",c[n-1]);
}
return 0;
}