体会到了状态转移,化简方程的重要性
题解转自http://blog.csdn.net/morgan_xww/article/details/6776947
/**
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);
= 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则无解...
**/
1 //#pragma comment(linker,"/STACK:102400000,102400000") 2 #include <map> 3 #include <set> 4 #include <stack> 5 #include <queue> 6 #include <cmath> 7 #include <ctime> 8 #include <vector> 9 #include <cstdio> 10 #include <cctype> 11 #include <cstring> 12 #include <cstdlib> 13 #include <iostream> 14 #include <algorithm> 15 using namespace std; 16 #define INF 1e8 17 #define inf (-((LL)1<<40)) 18 #define lson k<<1, L, mid 19 #define rson k<<1|1, mid+1, R 20 #define mem0(a) memset(a,0,sizeof(a)) 21 #define mem1(a) memset(a,-1,sizeof(a)) 22 #define mem(a, b) memset(a, b, sizeof(a)) 23 #define FOPENIN(IN) freopen(IN, "r", stdin) 24 #define FOPENOUT(OUT) freopen(OUT, "w", stdout) 25 template<class T> T CMP_MIN(T a, T b) { return a < b; } 26 template<class T> T CMP_MAX(T a, T b) { return a > b; } 27 template<class T> T MAX(T a, T b) { return a > b ? a : b; } 28 template<class T> T MIN(T a, T b) { return a < b ? a : b; } 29 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; } 30 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } 31 32 //typedef __int64 LL; 33 //typedef long long LL; 34 const int MAXN = 10005; 35 const int MAXM = 100005; 36 const double eps = 1e-10; 37 //const LL MOD = 1000000007; 38 39 int T, N; 40 vector<int>v[MAXN]; 41 double k[MAXN], e[MAXN]; 42 double A[MAXN], B[MAXN], C[MAXN]; 43 44 45 void init() 46 { 47 int U, V; 48 scanf("%d", &N); 49 for(int i=0;i<=N;i++) v[i].clear(); 50 for(int i=0;i<N-1;i++) 51 { 52 scanf("%d %d", &U, &V); 53 v[U].push_back(V); 54 v[V].push_back(U); 55 } 56 for(int i=1;i<=N;i++) 57 { 58 scanf("%d %d", &U, &V); 59 k[i] = (double)U / 100.0; 60 e[i] = (double)V / 100.0; 61 } 62 } 63 64 bool DFS(int x, int fa) 65 { 66 A[x] = k[x]; 67 B[x] = (1 - k[x] - e[x]) / v[x].size(); 68 C[x] = 1 - k[x] - e[x]; 69 if(v[x].size() == 1 && x != fa) 70 return true; 71 double temp = 0; 72 for(int i = 0; i < v[x].size() ; i ++ ) 73 { 74 int y = v[x][i]; 75 if(y == fa) continue; 76 if(!DFS(y, x)) return false; 77 A[x] += A[y] * B[x]; 78 C[x] += C[y] * B[x]; 79 temp += B[y] * B[x]; 80 } 81 if(fabs(temp - 1.0) < eps) return false; 82 A[x] = A[x] / (1 - temp); 83 B[x] = B[x] / (1 - temp); 84 C[x] = C[x] / (1 - temp); 85 return true; 86 } 87 88 int main() 89 { 90 //FOPENIN("in.txt"); 91 scanf("%d", &T); 92 for(int t = 1; t <= T; t ++ ) 93 { 94 init(); 95 if( DFS(1, 1) && fabs(A[1] - 1.0) > eps ) 96 { 97 printf("Case %d: %lf\n", t, C[1] / (1 - A[1])); 98 } 99 else 100 { 101 printf("Case %d: impossible\n", t); 102 } 103 } 104 }
HDU 4035Maze(概率DP)