期望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;
}
原文地址:https://www.cnblogs.com/FridayZ/p/14020898.html