hdu 4035 概率dp

太吊了

  1 /*

  2 HDU 4035

  3 

  4     dp求期望的题。

  5     题意:

  6     有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,

  7     从结点1出发,开始走,在每个结点i都有3种可能:

  8         1.被杀死,回到结点1处(概率为ki)

  9         2.找到出口,走出迷宫 (概率为ei)

 10         3.和该点相连有m条边,随机走一条

 11     求:走出迷宫所要走的边数的期望值。

 12 

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

 14 

 15     叶子结点:

 16     E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);

 17          = ki*E[1] + (1-ki-ei)*E[father[i]] + (1-ki-ei);

 18 

 19     非叶子结点:(m为与结点相连的边数)

 20     E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );

 21          = ki*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei)/m*∑(E[child[i]]) + (1-ki-ei);

 22 

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

 24 

 25     对于非叶子结点i,设j为i的孩子结点,则

 26     ∑(E[child[i]]) = ∑E[j]

 27                    = ∑(Aj*E[1] + Bj*E[father[j]] + Cj)

 28                    = ∑(Aj*E[1] + Bj*E[i] + Cj)

 29     带入上面的式子得

 30     (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;

 31     由此可得

 32     Ai =        (ki+(1-ki-ei)/m*∑Aj)   / (1 - (1-ki-ei)/m*∑Bj);

 33     Bi =        (1-ki-ei)/m            / (1 - (1-ki-ei)/m*∑Bj);

 34     Ci = ( (1-ki-ei)+(1-ki-ei)/m*∑Cj ) / (1 - (1-ki-ei)/m*∑Bj);

 35 

 36     对于叶子结点

 37     Ai = ki;

 38     Bi = 1 - ki - ei;

 39     Ci = 1 - ki - ei;

 40 

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

 42 

 43     E[1] = A1*E[1] + B1*0 + C1;

 44     所以

 45     E[1] = C1 / (1 - A1);

 46     若 A1趋近于1则无解...

 47 

 48 */

 49 #include<stdio.h>

 50 #include<string.h>

 51 #include<algorithm>

 52 #include<iostream>

 53 #include<math.h>

 54 #include<vector>

 55 using namespace std;

 56 const int MAXN=10010;

 57 const double eps=1e-9;//这里1e-8会WA。设为1e-9和1e-10可以

 58 double k[MAXN],e[MAXN];

 59 double A[MAXN],B[MAXN],C[MAXN];

 60 

 61 vector<int>vec[MAXN];//存树

 62 

 63 bool dfs(int t,int pre)//t的根结点是pre

 64 {

 65     int m=vec[t].size();//点t的度

 66     A[t]=k[t];

 67     B[t]=(1-k[t]-e[t])/m;

 68     C[t]=1-k[t]-e[t];

 69     double tmp=0;

 70     for(int i=0;i<m;i++)

 71     {

 72         int v=vec[t][i];

 73         if(v==pre)continue;

 74         if(!dfs(v,t))return false;

 75         A[t]+=(1-k[t]-e[t])/m*A[v];

 76         C[t]+=(1-k[t]-e[t])/m*C[v];

 77         tmp+=(1-k[t]-e[t])/m*B[v];

 78     }

 79     if(fabs(tmp-1)<eps)return false;

 80     A[t]/=(1-tmp);

 81     B[t]/=(1-tmp);

 82     C[t]/=(1-tmp);

 83     return true;

 84 }

 85 int main()

 86 {

 87    // freopen("in.txt","r",stdin);

 88    // freopen("out.txt","w",stdout);

 89     int T;

 90     int n;

 91     int u,v;

 92     int iCase=0;

 93     scanf("%d",&T);

 94     while(T--)

 95     {

 96         iCase++;

 97         scanf("%d",&n);

 98         for(int i=1;i<=n;i++)vec[i].clear();

 99         for(int i=1;i<n;i++)

100         {

101             scanf("%d%d",&u,&v);

102             vec[u].push_back(v);

103             vec[v].push_back(u);

104         }

105         for(int i=1;i<=n;i++)

106         {

107             scanf("%lf%lf",&k[i],&e[i]);

108             k[i]/=100;

109             e[i]/=100;

110         }

111         printf("Case %d: ",iCase);

112         if(dfs(1,-1)&&fabs(1-A[1])>eps)

113         {

114             printf("%.6lf\n",C[1]/(1-A[1]));

115         }

116         else printf("impossible\n");

117     }

118 }

 

你可能感兴趣的:(HDU)