1. 程式人生 > 其它 >96. 奇怪的漢諾塔

96. 奇怪的漢諾塔

漢諾塔問題,條件如下:

1、這裡有 \(A、B、C\)\(D\) 四座塔。

2、這裡有 \(n\) 個圓盤,\(n\) 的數量是恆定的。

3、每個圓盤的尺寸都不相同。

4、所有的圓盤在開始時都堆疊在塔 \(A\) 上,且圓盤尺寸從塔頂到塔底逐漸增大。

5、我們需要將所有的圓盤都從塔 \(A\) 轉移到塔 \(D\) 上。

6、每次可以移動一個圓盤,當塔為空塔或者塔頂圓盤尺寸大於被移動圓盤時,可將圓盤移至這座塔上。

請你求出將所有圓盤從塔 \(A\) 移動到塔 \(D\),所需的最小移動次數是多少。

漢諾塔塔參考模型

輸入格式

沒有輸入

輸出格式

對於每一個整數 \(n\),輸出一個滿足條件的最小移動次數,每個結果佔一行。

資料範圍

\(1≤n≤12\)

輸入樣例:

沒有輸入
輸出樣例:
參考輸出格式

解題思路

遞迴

考慮先將上層中的 \(i\) 個盤子在四塔模式下移到 \(C\) 柱,因為這時在四塔模式下移動的次數最小,且由於是上層,不受 \(A\) 柱其他盤子的限制,然後再將剩餘的盤子在三塔模式下移到 \(D\) 柱,此時 \(C\) 柱受到限制,所以是三塔模式,最後再將 \(C\) 柱上的盤子在四塔模式下移到 \(D\) 柱,所以函式表示為 \(f[i]=min(2\times f[j],d[n-j])\),其中 \(d[i]\) 表示三塔模式下的最少移動次數

  • 時間複雜度:\(O(n^2)\)

程式碼

// Problem: 奇怪的漢諾塔
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/98/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=13;
int d[N],f[N];
int main()
{
    for(int i=1;i<=12;i++)d[i]=2*d[i-1]+1;
    memset(f,0x3f,sizeof f);
    f[1]=1;
 	for(int i=1;i<=12;i++)
 	{
 	    for(int j=1;j<=i;j++)f[i]=min(f[i],2*f[j]+d[i-j]);
 	    cout<<f[i]<<'\n';
 	}
    return 0;
}