poj1958 Strange Towers of Hanoi

題目大意

根據經典的漢諾塔問題改編而來。
漢諾塔(帶過程的)

題解

原漢諾塔

我們設d[i] 爲把i 個盤子轉移的步數。
我們稱使用三個塔的轉移稱爲三塔模式。
因爲當i>=2 的時候,二塔模式無解,所以我們對i 個盤子轉移的時候,只能分爲1i1 兩個部分。
所以我們可以模擬:
A 柱子三塔模式下轉移i1 個到B ,把剩下的1 個盤子三塔模式下轉移到C ,然後把B 柱子上i1 個盤子轉移到C 柱子上去。
所以d[n]=2d[n1]+1

迴歸本題

這裏,我們要明確的一個問題就是,對於不能轉移的一個塔來說,剩餘的三個塔是能夠完成一堆盤子的轉移的,也就是說,我們轉移模式存在了三塔模式和四塔模式兩個模式。
因此我們還需要枚舉把n 個盤子分成兩堆幾個盤子。
我們四塔模式下轉移n 個盤子的方法是這樣的:現在四塔模式下從A 柱子到B 柱子轉移i 個盤子,然後在三塔模式下從A 柱子轉移到D 柱子ni 個盤子,最後在四塔模式下從B 柱子到C 柱子轉移i 個盤子。我們設f[i] 爲四塔模式的轉移步驟數。
也就是說f[i]=min{2f[i]+d[ni]}
ok了。
我們還可以用這個方法擴展到m 塔。

code

#include <iostream> 
#include <cstdio> 
#include <fstream> 
#include <algorithm> 
#include <cmath> 
#include <deque> 
#include <vector> 
#include <queue> 
#include <string> 
#include <cstring> 
#include <map> 
#include <stack> 
#include <set> 
using namespace std;
inline int read(){
    int num=0;char c=' ';bool flag=true;
    for(;c>'9'||c<'0';c=getchar())
        if(c=='-')
            flag=false;
    for(;c>='0'&&c<='9';num=(num<<3)+(num<<1)+c-48,c=getchar());
    return flag ? num : -num;
}
const int INF = 0x3F3F3F3F;
const int maxn = 2000;
int n,d[maxn],f[maxn];
int main(){
    n = 12;
    memset(d, 0, sizeof d);
    d[0]=0; 
    for(int i = 1; i <= n; i++) {
        d[i] = 2 * d[i-1] + 1;
    }
    memset(f, 0,sizeof d);
    f[0] = 0;
    f[1] = 1;
    for(int i = 2; i <= n; i++) {
        int t = INF;
        for(int j = 1;j < i; j++) {
            t = min(2 * f[j] + d[i-j], t);
        }
        f[i] = t;
    }
    for(int i = 1; i <= n; i++)
        printf("%d\n",f[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章