題目大意
根據經典的漢諾塔問題改編而來。
漢諾塔(帶過程的)
題解
原漢諾塔
我們設 爲把 個盤子轉移的步數。
我們稱使用三個塔的轉移稱爲三塔模式。
因爲當 的時候,二塔模式無解,所以我們對 個盤子轉移的時候,只能分爲 兩個部分。
所以我們可以模擬:
從 柱子三塔模式下轉移 個到 ,把剩下的 個盤子三塔模式下轉移到 ,然後把 柱子上 個盤子轉移到 柱子上去。
所以
迴歸本題
這裏,我們要明確的一個問題就是,對於不能轉移的一個塔來說,剩餘的三個塔是能夠完成一堆盤子的轉移的,也就是說,我們轉移模式存在了三塔模式和四塔模式兩個模式。
因此我們還需要枚舉把 個盤子分成兩堆幾個盤子。
我們四塔模式下轉移 個盤子的方法是這樣的:現在四塔模式下從 柱子到 柱子轉移 個盤子,然後在三塔模式下從 柱子轉移到 柱子 個盤子,最後在四塔模式下從 柱子到 柱子轉移 個盤子。我們設 爲四塔模式的轉移步驟數。
也就是說
ok了。
我們還可以用這個方法擴展到 塔。
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;
}