太吊了,反正我不会
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 }
时间: 2024-11-03 21:57:00