HDU--4035(概率DP,公式推导与化简)
2015-04-24 19:33:18
题目:给你一棵树,一个人一开始从节点1(根)出发,等概率地选择相邻节点行走,每到一个节点 i 有 Ki 的概率被杀死,并回到节点1,有 Ei 的概率逃出这棵树。问这个人逃出这棵树要经过的期望路径数。
思路:这道题很好地体现了概率DP的特点:公式推导!一开始觉得这题很烦... 但是看了别人也没写得多难,于是果断开始推。
我们定义 dp[i]为从节点 i 出发到逃出要经过的期望路径数。那么对于一个节点我们可以列出方程:
,m 表示节点 i 有 m 个相邻节点。
发现 i 的每个儿子 ch[j] 的 dp[ch[j]] 都可以带入 dp[i] 中,将 dp[i] 的系数换元:
(Aofch[j]表示 dp[ch[j]] 表达式中的 A)
于是有: (A' = A / (1 - C))
由上面式子可以发现,如果从节点1递归下去直到叶子节点,在回溯过程中把系数逐步计算出来,那么dp[1]也就很好计算了。
显然:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=0;i<(n);++i) 17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 18 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 19 #define MP(a,b) make_pair(a,b) 20 #define PB(a) push_back(a) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 const int MAXN = 10010; 26 const double eps = 1e-9; 27 28 int T,N,m[MAXN]; 29 double dp[MAXN],K[MAXN],E[MAXN]; 30 double A[MAXN],B[MAXN],C[MAXN],D[MAXN]; 31 vector<int> g[MAXN]; 32 33 void Solve(int p,int pre){ 34 //printf("p : %d\n",p); 35 A[p] = K[p]; 36 B[p] = (1.0 - K[p] - E[p]) / m[p]; 37 C[p] = 0.0; 38 D[p] = 1.0 - K[p] - E[p]; 39 for(int i = 0; i < m[p]; ++i){ 40 int v = g[p][i]; 41 if(v == pre) continue; 42 Solve(v,p); 43 A[p] += B[p] * A[v]; 44 D[p] += B[p] * D[v]; 45 C[p] += B[p] * B[v]; 46 } 47 A[p] /= (1.0 - C[p]); 48 B[p] /= (1.0 - C[p]); 49 D[p] /= (1.0 - C[p]); 50 } 51 52 int main(){ 53 int a,b; 54 scanf("%d",&T); 55 FOR(tt,1,T){ 56 scanf("%d",&N); 57 FOR(i,1,N) g[i].clear(); 58 REP(i,N - 1){ 59 scanf("%d%d",&a,&b); 60 g[a].PB(b); 61 g[b].PB(a); 62 } 63 FOR(i,1,N) m[i] = g[i].size(); 64 FOR(i,1,N){ 65 scanf("%lf%lf",&K[i],&E[i]); 66 K[i] /= 100.0; 67 E[i] /= 100.0; 68 } 69 Solve(1,0); 70 printf("Case %d: ",tt); 71 if(fabs(1 - A[1]) < eps) printf("impossible\n"); 72 else{ 73 dp[1] = D[1] / (1 - A[1]); 74 printf("%.6f\n",dp[1]); 75 } 76 } 77 return 0; 78 }