N 條路(N≤100),初始戰力 f(≤10000)。每天隨機選一條路(概率 1/N)。第 i 條路難度 c_i:
f > c_i:花費 t_i = floor(φ·c_i²) 天逃脫(φ=(1+√5)/2)。c_i,繼續。求逃脫期望天數。多測試用例。
E(f):當前戰力為 f 時的期望剩餘天數。
遞推:
E(f) = (1/N) * Σ_{i=1..N} {
f > c_i ? t_i : (1 + E(f + c_i))
}
f。最大戰力:初始 ≤10000,每次增加 ≤10000,最多增加 N 次?實際上 f 遞增,最終必超過所有 c_i,遞歸有界。c_i,但期望步數有限。數組開 dp[20005] 足夠(題目保證答案 ≤ 1e9)。#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXF = 20005;
double dp[MAXF];
int c[105];
int n, f0;
const double phi = (1 + sqrt(5.0)) / 2;
double dfs(int f) {
if (dp[f] > 0) return dp[f];
double ans = 0;
for (int i = 0; i < n; ++i) {
if (f > c[i]) {
int t = (int)(phi * c[i] * c[i]); // floor 隱含在轉換中
ans += t * 1.0 / n;
} else {
ans += (1.0 + dfs(f + c[i])) / n;
}
}
return dp[f] = ans;
}
int main() {
while (~scanf("%d%d", &n, &f0)) {
for (int i = 0; i < n; ++i) scanf("%d", &c[i]);
memset(dp, 0, sizeof(dp));
printf("%.3f\n", dfs(f0));
}
return 0;
}
E = Σ p_i * (cost_i + E_next),p_i = 1/N。(1+sqrt(5))/2,用 double 精度足夠。(int)(phi * c[i] * c[i]) 等價於 floor。f 最大約 f0 + Σ c_i ≤ 10000 + 100×10000 = 1e6?但題目保證答案 ≤ 1e9,實際測試 dp[20005] 足夠(或用 map)。為保險可用 unordered_map 或開大數組 dp[200005]。%.3f 保留三位小數。f0 遞增至 > max(c_i),步長不定,但每狀態計算 O(N),總時間可接受。ZOJ 3640 是「概率 DP + 記憶化搜索」的典型應用。關鍵在於:
E(f) = Σ p_i * (即時花費 + 後續期望)。double 足夠,輸出 %.3f。此模板適用於所有「狀態單向轉移、隨機選擇動作、求期望步數/代價」問題。