HDU-4035 Maze 概率DP

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4035

  很不错的概率DP题目,因为这题是无向图,所以要对叶节点和非叶节点考虑,然后列出方程后,因为数据很大,高斯消元如果不特定优化会超时,可以转化方程,然后求解系数。

解法:<摘自KB神>

题意:
有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 //STATUS:C++_AC_281MS_1440KB

  2 #include <functional>

  3 #include <algorithm>

  4 #include <iostream>

  5 //#include <ext/rope>

  6 #include <fstream>

  7 #include <sstream>

  8 #include <iomanip>

  9 #include <numeric>

 10 #include <cstring>

 11 #include <cassert>

 12 #include <cstdio>

 13 #include <string>

 14 #include <vector>

 15 #include <bitset>

 16 #include <queue>

 17 #include <stack>

 18 #include <cmath>

 19 #include <ctime>

 20 #include <list>

 21 #include <set>

 22 #include <map>

 23 using namespace std;

 24 //#pragma comment(linker,"/STACK:102400000,102400000")

 25 //using namespace __gnu_cxx;

 26 //define

 27 #define pii pair<int,int>

 28 #define mem(a,b) memset(a,b,sizeof(a))

 29 #define lson l,mid,rt<<1

 30 #define rson mid+1,r,rt<<1|1

 31 #define PI acos(-1.0)

 32 //typedef

 33 typedef __int64 LL;

 34 typedef unsigned __int64 ULL;

 35 //const

 36 const int N=10010;

 37 const int INF=0x3f3f3f3f;

 38 const int MOD=10007,STA=8000010;

 39 const LL LNF=1LL<<55;

 40 const double EPS=1e-9;

 41 const double OO=1e30;

 42 const int dx[4]={-1,0,1,0};

 43 const int dy[4]={0,1,0,-1};

 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

 45 //Daily Use ...

 46 inline int sign(double x){return (x>EPS)-(x<-EPS);}

 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}

 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}

 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}

 50 template<class T> inline T Min(T a,T b){return a<b?a:b;}

 51 template<class T> inline T Max(T a,T b){return a>b?a:b;}

 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}

 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}

 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}

 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}

 56 //End

 57 

 58 vector<int> q[N];

 59 double k[N],e[N],A[N],B[N],C[N];

 60 int T,n;

 61 

 62 void dfs(int u,int fa)

 63 {

 64     int i,j,v,m=q[u].size();

 65     double P=(1-k[u]-e[u])/(m);

 66     double At,Bt,Ct;

 67     At=Bt=Ct=0;

 68     for(i=0;i<m;i++){

 69         v=q[u][i];

 70         if(v==fa)continue;

 71         dfs(v,u);

 72         At+=A[v];

 73         Bt+=B[v];

 74         Ct+=C[v];

 75     }

 76     A[u]=(P*At+k[u])/(1-P*Bt);

 77     B[u]=P/(1-P*Bt);

 78     C[u]=(P*Ct+1-k[u]-e[u])/(1-P*Bt);

 79 }

 80 

 81 int main(){

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

 83     int ca=1,i,j,a,b;

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

 85     while(T--)

 86     {

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

 88         for(i=1;i<=n;i++)q[i].clear();

 89         for(i=1;i<n;i++){

 90             scanf("%d%d",&a,&b);

 91             q[a].push_back(b);

 92             q[b].push_back(a);

 93         }

 94         for(i=1;i<=n;i++){

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

 96             k[i]/=100,e[i]/=100;

 97         }

 98 

 99         dfs(1,0);

100 

101         printf("Case %d: ",ca++);

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

103         else printf("impossible\n");

104     }

105     return 0;

106 }

 

你可能感兴趣的:(HDU)