解析:
1、先看汉诺塔1的情况
a、只有一个盘子时,只需挪动一步;
b、假如n个盘子要移动An步,则有n+1个盘子可以先通过An步把上面的n个盘子挪到第二个柱子上,再挪最大的盘子,最后把n个盘子挪到大的上面,总共2An+1步,则有A(n+1)=2An+1。
c、以上式子可推得An=2^n-1。
2、回过来看该題,该题多加了一根柱子,现在有四根柱子了,分别是a,b,c,d,计算将n个盘从第一根柱子a全部移到最后一根柱子d上所需的最少步数,而且不能够出现大的盘子放在小的盘子上面。
a、设F[n]为所求的最小步数,则有当n=1时,F[n]=1;当n=2时,F[n]=3;这里同经典汉诺塔一样,将移动盘子的任务分为三步:
b、将x(1<=x<=n)个盘从a柱依靠b,d柱移到c柱,这个过程需要步数设为F[x];
c、将a柱上剩下的n-x个盘依靠b柱移到d柱(此时不能依靠c柱,c柱上的所有盘都比a柱上的盘小),移动方式相当于是一个汉诺塔1版,这个过程需要的步数为2^(n-x)-1(汉诺塔一);
d、将c柱上的x个盘依靠a,b柱移到d柱上,这个过程同样需要的步数为F[x];
e、经过以上3步即可完成任务,总步数为F[n]=F[x]+2^(n-x)-1+F[x]=2*F[x]+2^(n-x)-1;题目中要求的是最少的步数,根据上式,x的不同取值,对于同一个n,也会得出不同的F[n]。因此答案转化为min{2*F[x]+2^(n-x)-1},其中1<=x<=n;循环遍历x的各个取值,记录最小值即可。
#include<iostream> #include<cmath> using namespace std; int main() { __int64 max=0x7FFFFFFFFFFFFFFF,f[65],min; int i,j,n; f[1]=1;f[2]=3; for(i=3;i<65;i++) { min=max; for(j=1;j<i;j++) if(2*f[j]+pow(2.0,i-j)-1<min) min=2*f[j]+pow(2.0,i-j)-1; f[i]=min; } while(cin>>n) { printf("%I64d\n",f[n]); } return 0; }
原文地址:http://blog.csdn.net/a809146548/article/details/44313041