HDU1207:汉诺塔II

来源:互联网 发布:淘宝外卖红包免费领取 编辑:程序博客网 时间:2024/06/05 23:56

HDU1207
Problem Description
经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。Gardon就收到了一个汉诺塔玩具作为生日礼物。
  Gardon是个怕麻烦的人(恩,就是爱偷懒的人),很显然将64个圆盘逐一搬动直到所有的盘子都到达第三个柱子上很困难,所以Gardon决定作个小弊,他又找来了一根一模一样的柱子,通过这个柱子来更快的把所有的盘子移到第三个柱子上。下面的问题就是:当Gardon在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?

Input
包含多组数据,每个数据一行,是盘子的数目N(1<=N<=64)。

Output
对于每组数据,输出一个数,到达目标需要的最少的移动数。

Sample Input
1
3
12
Sample Output
1
5
81

题解

设 f[n] 为所求的最小步数
可发现n=1,n=2时与经典汉诺塔问题无异
对于任意n,分为三步
(1)将最上面x个圆盘由a依靠bd移动到c,步数为f[x]
(2)将剩下的n-x个圆盘由a依靠b移动到d,步数为2^(n-x)-1(经典汉诺塔)
(3)将c上x个圆盘依靠ab移动到d,步数为f[x]
则f[n] = min{ 2 * f[x] + 2^(n-x)-1 } (1 <= x <= n)

#include<cstdio>#include<iostream>#include<cmath>#define ll long longusing namespace std;const int inf = 1<<30;int n;ll ans, f[100];void work(){    f[1] = 1; f[2] = 3;    for(int i = 3; i <= 64; i++){        ans = inf;        for(int j = 1; j < i; j++){            if((f[j] << 1) + pow(2.0, i-j) - 1 < ans)                 ans = (f[j] << 1) + pow(2.0, i-j) - 1;        }        f[i] = ans;    }}    int main(){    work();    while(~scanf("%d", &n)){        cout<< f[n]<< endl;    }    return 0;}
1 0
原创粉丝点击