經典漢諾塔有三根柱子,n 個盤子從柱子 1 移到柱子 3。標準最少步數 f[n] = 2*f[n-1] + 1,f[1]=1。現改為隨機策略:每次將最大的盤子 n 隨機放到三根柱子之一(概率各 1/3),然後遞歸移動剩餘 n-1 個盤子。求期望步數 dp[n]。
考慮最大盤子 n 的隨機放置:
n-1 個盤子移到柱子 2(期望 dp[n-1]),再將它們移到柱子 3(標準步數 f[n-1]),共 dp[n-1] + f[n-1] + 1 步(+1 為移動盤子 n)。n-1 個盤子移到柱子 2(dp[n-1]),移動盤子 n 到柱子 3(1 步),再將 n-1 個盤子從柱子 2 移到柱子 3(標準 f[n-1]),共 dp[n-1] + f[n-1] + 1 步。n-1 盤子的隨機過程,期望 dp[n-1] 步。dp[n] = (1/3)*dp[n-1] + (2/3)*(dp[n-1] + f[n-1] + 1) = dp[n-1] + (2/3)*(f[n-1] + 1)。
初始 dp[1] = 2/3(盤子 1 隨機放三根柱子,1/3 已在目標,2/3 需移動 1 步)。
預計算 f[i] 和 dp[i] 至 i=100,每組查詢 O(1) 輸出 dp[n] 保留兩位小數。
#include <cstdio>
const int N = 105;
double f[N], dp[N];
int main() {
f[1] = 1;
for (int i = 2; i < N; ++i) f[i] = 2*f[i-1] + 1;
dp[1] = 2.0/3;
for (int i = 2; i < N; ++i)
dp[i] = dp[i-1] + 2.0/3 * (f[i-1] + 1);
int T, n; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
printf("%.2f\n", dp[n]);
}
return 0;
}