1. 程式人生 > >HDU1207 漢諾塔II 【遞推】

HDU1207 漢諾塔II 【遞推】

漢諾塔II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4799    Accepted Submission(s): 2362

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
參考資料:
#include <stdio.h>
#include <math.h>

__int64 dp[66] = {0, 1, 3, 5}, pow2[66] = {1, 2, 4, 8, 16};

int main()
{
    int n, r, i;
    for(i = 5; i < 65; ++i)
        pow2[i] = pow2[i-1] << 1;
    for(n = 4; n < 65; ++n){
        r = (int)((sqrt(8 * n + 1) - 1) / 2);
        dp[n] = 2 * dp[n-r] + pow2[r] - 1;
    }
    while(scanf("%d", &n) != EOF){
        printf("%I64d\n", dp[n]);
    }
    return 0;
}