• 期望DP——HDU4035Maze


    Description

    HDU传送门

    题目简述:

    你被困在一个迷宫里面,这个迷宫是一颗树,每一个结点都有一个出口,且第(i)结点都有三种可能:

    1. (k_i)的概率被杀死,杀死后你会回到1号结点
    2. (e_i)的概率逃脱
    3. (1-k_i-e_i)的概率从与(i)相邻的(m)条边出去(所以走与(i)相邻一条边的概率是(frac {1-k_i-e_i}{m})

    求逃出迷宫的期望步数。

    Solution

    假设(dp_i)表示从第(i)个结点出发逃脱的期望步数,(f_i)(i)号结点的父亲结点,(son_i)(i)号结点的儿子结点,那么有:

    [egin{cases} i点非叶子结点时:\ dp_i=k_i*dp_1+e_i*0+frac{1-k_i-e_i}{m}*(dp_{f_i}+1+sum (dp_{son_i}+1) )\ =k_i*dp_1+frac {1-k_i-e_i}{m}*dp_{f_i}+frac {1-k_i-e_i}{m}*sum dp_{son_i}+1-k_i-e_i\ i点为叶子结点时:\ dp_i=k_i*dp_1+(1-k_i-e_i)*(dp_{f_i}+1)\ =k_i*dp_1+(1-k_i-e_i)*dp_{f_i}+1-k_i-e_i end{cases} ]

    发现可以把它们设置成统一形式:(dp_i=A_i*dp_1+B_i*dp_{f_i}+C_i)

    对于非叶子结点(i),设它的儿子为(j)

    (sum dp_{son_i}=sum (A_j*dp_1+B_j*dp_i+C_j)\dp_i=A_i*dp_1+B_i*dp_{f_i}+frac {1-k_i-e_i}{m}*sum(A_{son_i}*dp_1+B_{son_i}*dp_i+C_{son_i})+1-k_i-e_i\=(A_i+(sum A_{son_i})*frac {1-k_i-e_i}{m})*dp_1+B_i*dp_{f_i}+frac {1-k_i-e_i}{m}*(sum B_{son_i})*dp_i+frac {1-k_i-e_i}{m}*sum C_{son_i}+1-k_i-e_i\ herefore (1-frac {1-k_i-e_i}{m}*sum B{son_i})*dp_i=(k_i+(sum A_{son_i})*frac {1-k_i-e_i}{m})*dp_1+frac {1-k_i-e_i}{m}*dp_{f_i}+frac {1-k_i-e_i}{m}*sum C_{son_i}+1-k_i-e_i\)

    这样下来,(dp_i)(A_i,B_i,C_i)都只与儿子结点有关了,就可以从下往上计算,最终答案就是(dp_1)

    注意:如果有一个结点的逃脱期望步数是0,那么无解,因为有可能一直在循环。

    Code

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define sz(x) (int)x.size()
    using namespace std;
    const int N=1e4+5;
    int T,n,du[N];
    double p[N][3],A[N],B[N],C[N];
    vector<int> e[N];
    
    inline int read () {
        int res=0,fl=1;
        char ch;
        while ((ch=getchar())&&(ch<'0'||ch>'9')) if (ch=='-') fl=-1;
        res=ch^48;
        while ((ch=getchar())&&ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^48);
        return res*fl;
    }
    
    inline bool dfs (int x,int fa) {//cout<<x<<endl;
        int son=du[x];
        A[x]=p[x][0];
        B[x]=p[x][2]/son;
        C[x]=p[x][2];
        double tmp=0;
        for (int i=0;i<sz(e[x]);i++) {
            int v=e[x][i];
            if (v==fa) continue;
            if (!dfs(v,x)) return false;
            A[x]+=p[x][2]/son*A[v];
            C[x]+=p[x][2]/son*C[v];
            tmp+=p[x][2]/son*B[v];
        }
        if (fabs(1-tmp)<1e-9) return false;
        A[x]/=1-tmp;
        B[x]/=1-tmp;
        C[x]/=1-tmp;
        return true;
    }
    
    inline void clean () {
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        memset(C,0,sizeof(C));
        memset(du,0,sizeof(du));
        for (int i=1;i<=n;i++) e[i].clear();
    }
    
    int main () {
    //    freopen("4035.in","r",stdin);
    //    freopen("4035.out","w",stdout);
        T=read();
        for (int t=1;t<=T;t++) {
            n=read();
            clean();
            for (int i=1;i<n;i++) {
                int u=read(),v=read();du[u]++;du[v]++;
                e[u].push_back(v);e[v].push_back(u);
            }
            for (int i=1;i<=n;i++) p[i][0]=read()/100.0,p[i][1]=read()/100.0;
            for (int i=1;i<=n;i++) p[i][2]=1-p[i][0]-p[i][1];
    //        cout<<p[1][0]<<endl;
            printf("Case %d: ",t);
            if (dfs(1,1)&&fabs(1-A[1])>1e-9) printf("%.6lf
    ",C[1]/(1-A[1]));
            else puts("impossible");
        }
        return 0;
    }
    
  • 相关阅读:
    MVVM架构~knockoutjs实现简单的购物车
    Thrift架构~目录
    WebApi系列~在WebApi中实现Cors访问
    WebApi系列~基于RESTful标准的Web Api
    MVVM架构~目录
    IOS设计模式学习(20)命令
    MySQL保留关键字
    Eclipse with C++: "Launch failed. Binary not found."
    HTML5 Canvas鼠标与键盘事件
    通过openssh远程登录时的延迟问题解决
  • 原文地址:https://www.cnblogs.com/FridayZ/p/14020898.html
Copyright © 2020-2023  润新知