汉诺塔IITime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10139 Accepted Submission(s): 4949 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。Gardon就收到了一个汉诺塔玩具作为生日礼物。 Input 包含多组数据,每个数据一行,是盘子的数目N(1<=N<=64)。 Output 对于每组数据,输出一个数,到达目标需要的最少的移动数。 Sample Input 1 3 12 Sample Output 1 5 81 Author Gardon Source Recommend JGShining | We have carefully selected several similar problems for you: 1996 1995 1997 2184 2511 |
题解:参考:http://www.cnblogs.com/yinbiao/p/9371227.html
问题描述:在经典汉诺塔的基础上加一个条件,即,如果再加一根柱子(即现在有四根柱子a,b,c,d),计算将n个盘从第一根柱子(a)全部移到最后一根柱子(d)上所需的最少步数,当然,也不能够出现大的盘子放在小的盘子上面。注:1<=n<=64;
分析:设F[n]为所求的最小步数,显然,当n=1时,F[n]=1;当n=2时,F[n]=3;如同经典汉诺塔一样,我们将移完盘子的任务分为三步:
(1)将x(1<=x<=n)个盘从a柱依靠b,d柱移到c柱,这个过程需要的步数为F[x];
(2)将a柱上剩下的n-x个盘依靠b柱移到d柱(注:此时不能够依靠c柱,因为c柱上的所有盘都比a柱上的盘小)
些时移动方式相当于是一个经典汉诺塔,即这个过程需要的步数为2^(n-x)-1(证明见再议汉诺塔一);
(3)将c柱上的x个盘依靠a,b柱移到d柱上,这个过程需要的步数为F[x];
第(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的各个取值,并用一个标记变量min记录x的各个取值中F[n]的最小值。
#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<vector>
#include<bitset>
#include<iostream>
#include <bits/stdc++.h>
#define ullmax 1844674407370955161
#define llmax 9223372036854775807
#define intmax 2147483647
#define re register
using namespace std;
typedef unsigned long long ll;
ll po_w(ll a,ll b){
ll ans=1;
while(b){
if(b&1)
ans=ans*a;
b>>=1;
a*=a;
}
return ans;
}
ll per[65];
void fun(){
fill(per,per+65,llmax);
per[1]=1; per[2]=3;
for(int i=3;i<=64;i++){
for(int j=1;j<i;j++){
per[i]=min(per[i],2*per[j]+po_w(2,i-j)-1);
}
}
}
int main(){
int n;
fun();
while(scanf("%d",&n)!=EOF){
printf("%llu\n",per[n]);
}
return 0;
}