ZOJ3329(数学推导+期望递推)
要点:
1.期望的套路,要求n以上的期望,则设dp[i]为i分距离终点的期望步数,则终点dp值为0,答案是dp[0]。
2.此题主要在于数学推导,一方面是要写出dp[i] = 什么,虽然一大串但是思维上并不难;然后就是一种解方程的方法,因为都跟dp[0]有关,且dp[0]是个确定的常数,所以设dp[i] = A[i] * dp[0] + B[i],带入上面那一串解出A[i]、B[i],发现是个递推式,于是递推求出A[i]B[i]即可得到dp[0] = B[0] / (1 - A[0])。推荐邝斌聚聚博客。
式子出来了,代码就好写了:
1 int T, n, K1, K2, K3, a, b, c; 2 db p[20]; 3 db A[550], B[550]; 4 5 void GetPk() { 6 p[0] = 1.0 / K1 / K2 / K3; 7 rep(i, 1, K1) rep(j, 1, K2) rep(k, 1, K3) { 8 if (i == a && j == b && k == c) continue; 9 p[i + j + k] += p[0]; 10 } 11 } 12 13 void GetAB() { 14 irep(i, n, 0) { 15 A[i] = p[0]; 16 B[i] = 1; 17 rep(j, 3, K1 + K2 + K3) { 18 A[i] += A[i + j] * p[j]; 19 B[i] += B[i + j] * p[j]; 20 } 21 } 22 } 23 24 int main() { 25 ios_base::sync_with_stdio(false); 26 cin.tie(0); 27 for (cin >> T; T; T--) { 28 init(A, 0), init(B, 0), init(p, 0); 29 cin >> n >> K1 >> K2 >> K3 >> a >> b >> c; 30 GetPk(), GetAB(); 31 cout << fixed << setprecision(10) << B[0] / (1 - A[0]) << endl; 32 } 33 return 0; 34 }