HDU 4035 Maze(概率DP)

来源:互联网 发布:it编程 编辑:程序博客网 时间:2024/06/04 20:03

思路: (从kuangbin的博客里搬下来!!) 

    题意:
    有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则无解...

#include <stdio.h>#include <algorithm>#include <cstring>#include <iostream>#include <vector>using namespace std;const int maxn=20000;vector<int>vec[maxn];int du[maxn];bool yes;double k[maxn],e[maxn];double a[maxn], b[maxn], c[maxn];double ans;const double eps=1e-9;bool dfs(int u,int f){    if(du[u]==1&&f!=-1)    {        a[u]=k[u];        b[u]=1-k[u]-e[u];        c[u]=1-k[u]-e[u];        return true;    }    a[u]=k[u];    b[u]=(1-k[u]-e[u])/vec[u].size();    c[u]=1-k[u]-e[u];    double res=0;    for(int i=0;i<vec[u].size();i++)    {        int v=vec[u][i];        if(v==f) continue;        if(!dfs(v,u)) return false;        a[u]+=a[v]*b[u];        c[u]+=c[v]*b[u];        res+=b[v]*b[u];    }    if(fabs(res-1)<eps) return false;    a[u]/=1-res;    b[u]/=1-res;    c[u]/=1-res;    return true;}int main(){    int t;    scanf("%d",&t);    for(int cs=1;cs<=t;cs++)    {        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)            vec[i].clear();        ans=0;        memset(du,0,sizeof(du));        for(int i=1;i<n;i++)        {            int u,v;            scanf("%d%d",&u,&v);            vec[u].push_back(v);            vec[v].push_back(u);            du[u]++,du[v]++;        }        for(int i=1;i<=n;i++)        {            scanf("%lf%lf",&k[i],&e[i]);            k[i]/=100;            e[i]/=100;        }        yes=dfs(1,-1);        printf("Case %d: ",cs);        if(yes==false||fabs(1-a[1])<eps)        {            printf("impossible\n");        }else{            double resul=c[1]/(1-a[1]);            printf("%.7lf\n",c[1]/(1-a[1]));        }    }}


原创粉丝点击