1. 程式人生 > >hdu1207漢諾塔II

hdu1207漢諾塔II

問題描述:在經典漢諾塔的基礎上加一個條件,即,如果再加一根柱子(即現在有四根柱子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]; 故完成任務所需要的總的步數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]的最小值。 數值不是很大,int完全可以搞定,程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <cstdlib>
#define LL long long
using namespace std;
int f[100],minn;
void solve()
{
    f[1]=1;
    f[2]=3;
    for(int i=3;i<=64;i++)
    {
        f[i]=minn=99999999;
        for(int x=1;x<i;x++)
        {
            if(minn>2*f[x]+pow(2.0,i-x)-1)
            {
                minn=2*f[x]+pow(2.0,i-x)-1;//pow函式的用法要注意:2.0寫成2就錯了
                f[i]=minn;
            }
        }
    }
}
int main()
{
    int n;
    solve();
    while(cin>>n)
    {
        cout<<f[n]<<endl;
    }
    return 0;
}