要点:

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])。推荐邝斌聚聚博客

ZOJ3329(数学推导+期望递推)_qt

 

式子出来了,代码就好写了:

 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 }