hdu 4035 Maze (概率与期望DP)

题目描述

传送门

题目描述:一棵树,一个人初始在1号点。每次到达一个点,有ki的概率被杀死,并且回到1号点,有ei的概率直接逃离,然后等概率的逃到与他相邻的节点(1-ki-ei)/du[i],每次移动步数+1。 求逃出去的期望步数。

题解

这道题与上面题的思想和方法是类似的。
我们先假设逃离是到达节点0, 那么E[0]=0,倒着推。
对于叶子节点,他要么逃到他的父亲节点,要么被杀,要么直接逃离
E[i]=(1kiei)E[fa[i]]+kiE[1]+E[0]ei
因为E[0]=0 ,所以式子最终可以化简成 E[i]=(1kiei)E[fa[i]]+kiE[1]+(1kiei)
那么在这个式子中 E[fa[i]],E[1] 是未知量,那么我们可以把式子化简成
E[i]=A[i]E[fa[i]]+B[i]E[1]+C[i] 的形式。
对于非叶子节点
E[i]=(E[fa[i]]+1+(E[son[i]]+1))(1kiei)du[i]+E[1]ki
对于E[son[i]]来说,如果化成 E[i]=A[i]E[fa[i]]+B[i]E[1]+C[i] 的形式,那么我们可以发现 E[fa[son[i]]] 实际上就是E[i],那么我们可以对式子进行进一步的化简。
E[i]=(E[fa[i]]+1+(A[son[i]]E[i]+B[son[i]]E[1]+C[son[i]]+1))(1kiei)du[i]+E[1]ki
我们设 (1kiei)du[i]=p[i] 式子整理得
(1p[i]A[son[i]])E[i]=p[i]E[fa[i]]+(ki+p[i]B[son[i]])E[1]+(1kiei)+p[i]C[son[i]]
最后把 (1p[i]A[son[i]]) 除过来,就可以得到 A[i],B[i],C[i]
最后的答案就是 C[1]/(1B[1])
注意在计算的过程中只要E[i]的系数趋近与0,那就是impossible

代码

#include
#include
#include
#include
#include
#define N 200003
#define eps 1e-9
using namespace std;
int n,point[N],v[N],nxt[N],du[N],tot,T;
double A[N],B[N],C[N],k[N],e[N];
void add(int x,int y)
{
    tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; 
    tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
bool dfs(int x,int fa)
{
    A[x]=(1-k[x]-e[x])/du[x];
    B[x]=k[x];
    C[x]=1-k[x]-e[x];
    double t=1.0; double h=A[x];
    for (int i=point[x];i;i=nxt[i]) {
        if (v[i]==fa) continue;
        if (!dfs(v[i],x)) return false;
        t-=h*A[v[i]];
        B[x]+=h*B[v[i]];
        C[x]+=h*C[v[i]];
    }
    if (fabs(t)return false;
    A[x]/=t; B[x]/=t; C[x]/=t;
//  cout<
    return true;
}
int main()
{
    freopen("a.in","r",stdin);
    scanf("%d",&T);
    for (int t=1;t<=T;t++) {
        tot=0;  scanf("%d",&n);
        memset(point,0,sizeof(point));
        memset(du,0,sizeof(du));
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        memset(C,0,sizeof(C));
        for (int i=1;iint x,y; scanf("%d%d",&x,&y);
            add(x,y); du[x]++; du[y]++;
        }
        for (int i=1;i<=n;i++) {
            scanf("%lf%lf",&k[i],&e[i]);
            k[i]/=100.0; e[i]/=100.0;
        }
        bool pd=dfs(1,0);
        printf("Case %d: ",t);
        if (fabs(1.0-B[1])printf("impossible\n");
        else printf("%.6lf\n",C[1]/(1-B[1]));
    }
}

你可能感兴趣的:(动态规划,概率与期望)