hdu4035 Maze (树上dp求期望)

 dp求期望的题。
    题意:
    有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,
    从结点1出发,开始走,在每个结点i都有3种可能:
        1.被杀死,回到结点1处(概率为ki)
        2.找到出口,走出迷宫 (概率为ei)
        3.和该点相连有m条边,随机走一条
    求:走出迷宫所要走的边数的期望值。

    设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望。E[1]即为所求。

    叶子结点:
    E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);//因为是到达,i点跑出去的期望步数,所以逃出去的那个概率应该乘以0
         = ki*E[1] + (1-ki-ei)*E[father[i]] + (1-ki-ei);

    非叶子结点:(m为与结点相连的边数)
    E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );
         = ki*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei)/m*∑(E[child[i]]) + (1-ki-ei);

    设对每个结点:E[i] = Ai*E[1] + Bi*E[father[i]] + Ci;

    对于非叶子结点i,设j为i的孩子结点,则
    ∑(E[child[i]]) = ∑E[j]
                   = ∑(Aj*E[1] + Bj*E[father[j]] + Cj)
                   = ∑(Aj*E[1] + Bj*E[i] + Cj)
    带入上面的式子得
    (1 - (1-ki-ei)/m*∑Bj)*E[i] = (ki+(1-ki-ei)/m*∑Aj)*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei) + (1-ki-ei)/m*∑Cj;
    由此可得
    Ai =        (ki+(1-ki-ei)/m*∑Aj)   / (1 - (1-ki-ei)/m*∑Bj);
    Bi =        (1-ki-ei)/m            / (1 - (1-ki-ei)/m*∑Bj);
    Ci = ( (1-ki-ei)+(1-ki-ei)/m*∑Cj ) / (1 - (1-ki-ei)/m*∑Bj);

    对于叶子结点
    Ai = ki;
    Bi = 1 - ki - ei;
    Ci = 1 - ki - ei;

    从叶子结点开始,直到算出 A1,B1,C1;

    E[1] = A1*E[1] + B1*0 + C1;
    所以
    E[1] = C1 / (1 - A1);
    若 A1趋近于1则无解...
上面这一问题,中发现E[1]消不去,然后就用算出A,B,C的方式来求解。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 const int MAXN=10007;
 9 const double eps=1e-10;//这里1e-8会WA。设为1e-9和1e-10可以
10 double k[MAXN],e[MAXN];
11 double A[MAXN],B[MAXN],C[MAXN];
12 
13 int T,n,u,v,iCase;
14 vector<int>vec[MAXN];//存树
15 
16 bool dfs(int t,int pre)//t的根结点是pre
17 {
18     int m=vec[t].size();//点t的度
19     A[t]=k[t];
20     B[t]=(1-k[t]-e[t])/m;
21     C[t]=1-k[t]-e[t];
22     double tmp=0;
23     for(int i=0;i<m;i++)
24     {
25         int v=vec[t][i];
26         if(v==pre)continue;
27         if(!dfs(v,t))return false;
28         A[t]+=(1-k[t]-e[t])/m*A[v];
29         C[t]+=(1-k[t]-e[t])/m*C[v];
30         tmp+=(1-k[t]-e[t])/m*B[v];
31     }
32     if(fabs(tmp-1)<eps)return false;
33     A[t]/=(1-tmp);
34     B[t]/=(1-tmp);
35     C[t]/=(1-tmp);
36     return true;
37 }
38 int main()
39 {
40     scanf("%d",&T);
41     while(T--)
42     {
43         iCase++;
44         scanf("%d",&n);
45         for(int i=1;i<=n;i++)vec[i].clear();
46         for(int i=1;i<n;i++)
47         {
48             scanf("%d%d",&u,&v);
49             vec[u].push_back(v);
50             vec[v].push_back(u);
51         }
52         for(int i=1;i<=n;i++)
53         {
54             scanf("%lf%lf",&k[i],&e[i]);
55             k[i]/=100;
56             e[i]/=100;
57         }
58         printf("Case %d: ",iCase);
59         if(dfs(1,-1)&&fabs(1-A[1])>eps)
60         {
61             printf("%.6lf
",C[1]/(1-A[1]));
62         }
63         else printf("impossible
");
64     }
65 }
 
原文地址:https://www.cnblogs.com/fengzhiyuan/p/7673939.html