首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

BNU 34978 漢諾塔期望步數 - 動態規劃推導遞推公式

     編輯:C++ 入門

問題描述

經典漢諾塔有三根柱子,n 個盤子從柱子 1 移到柱子 3。標準最少步數 f[n] = 2*f[n-1] + 1,f[1]=1。現改為隨機策略:每次將最大的盤子 n 隨機放到三根柱子之一(概率各 1/3),然後遞歸移動剩餘 n-1 個盤子。求期望步數 dp[n]。

遞推關係推導

考慮最大盤子 n 的隨機放置:

  • 概率 1/3 放到目標柱子 3:需先將 n-1 個盤子移到柱子 2(期望 dp[n-1]),再將它們移到柱子 3(標準步數 f[n-1]),共 dp[n-1] + f[n-1] + 1 步(+1 為移動盤子 n)。
  • 概率 1/3 放到起始柱子 1:需將 n-1 個盤子移到柱子 2(dp[n-1]),移動盤子 n 到柱子 3(1 步),再將 n-1 個盤子從柱子 2 移到柱子 3(標準 f[n-1]),共 dp[n-1] + f[n-1] + 1 步。
  • 概率 1/3 放到中間柱子 2:直接進入 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] 保留兩位小數。

參考代碼 (C++)

#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;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved