HDU4035 Maze 【树形DP】【期望DP】
题目分析:
以前一直不会这个方法, 我好菜啊。
转移分为三个部分,一个是直接成功,一个是转移到E1,还有一个是转移到自己周围的一圈儿点。 如果是叶子那么只能转移到父亲,如果不是叶子可以把非叶子的转移代换,这样也只转移到父亲,判一下无解就行了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 10200; 5 const double eps = 1e-10; 6 7 int n,Tmp,cas; 8 double a[maxn],b[maxn]; 9 vector<int> g[maxn]; 10 11 double A[maxn],B[maxn],C[maxn]; 12 13 void dfs(int now,int f){ 14 int cnt = 0; 15 for(int i=0;i<g[now].size();i++){ 16 if(g[now][i] == f) continue; 17 cnt++; dfs(g[now][i],now); 18 } 19 if(cnt == 0){A[now] = a[now]; B[now] = 1-a[now]-b[now]; C[now] = B[now];} 20 else{ 21 double alpha = 0,beta = 0,gamma = 0; 22 for(int i=0;i<g[now].size();i++){ 23 if(g[now][i] == f) continue; 24 alpha += A[g[now][i]];beta += B[g[now][i]];gamma += C[g[now][i]]; 25 } 26 if(f != 0){ 27 gamma += cnt+1; 28 alpha *= (1-a[now]-b[now])/(cnt+1); 29 beta *= (1-a[now]-b[now])/(cnt+1); 30 gamma *= (1-a[now]-b[now])/(cnt+1); 31 B[now] = (1-a[now]-b[now])/(cnt+1); 32 beta = 1-beta; C[now] = gamma; A[now] = alpha+a[now]; 33 C[now] /= beta; A[now] /= beta; B[now] /= beta; 34 }else{ 35 gamma += cnt; 36 alpha *= (1-a[now]-b[now])/cnt; 37 beta *= (1-a[now]-b[now])/cnt; 38 gamma *= (1-a[now]-b[now])/cnt; 39 B[now] = 0; C[now] = gamma; beta = 1-(alpha+beta+a[now]); 40 if(beta <= eps){C[now] = -1;} 41 else C[now] /= beta; 42 } 43 } 44 } 45 46 void read(){ 47 scanf("%d",&n); 48 memset(A,0,sizeof(A)); 49 memset(B,0,sizeof(B)); 50 memset(C,0,sizeof(C)); 51 memset(a,0,sizeof(a)); 52 memset(b,0,sizeof(b)); 53 for(int i=1;i<=n;i++) g[i].clear(); 54 for(int i=1;i<n;i++){ 55 int u,v; scanf("%d%d",&u,&v); 56 g[u].push_back(v); g[v].push_back(u); 57 } 58 for(int i=1;i<=n;i++) { 59 int u,v; scanf("%d%d",&u,&v); 60 a[i] = u/100.0,b[i] = v/100.0; 61 } 62 } 63 64 void work(){ 65 dfs(1,0); 66 printf("Case %d: ",cas); 67 if(C[1] == -1){puts("impossible");} 68 else{printf("%.6lf\n",C[1]);} 69 } 70 71 int main(){ 72 scanf("%d",&Tmp); 73 while(cas++,Tmp--){ 74 read(); 75 work(); 76 } 77 return 0; 78 }