【HDU4035】Maze-期望DP+树形DP

来源:互联网 发布:安卓开发艺术探索源码 编辑:程序博客网 时间:2024/05/16 14:18

测试地址:Maze

题目大意:有一个树形的迷宫,有N个房间(标号为1~N)以及N-1条通道将它们连通,一开始在1号房间,每进入一个房间i,有k[i]的概率被陷阱杀死回到房间1,有e[i]的概率找到出口逃离迷宫,如果没有找到出口也没有被杀,那么就在与该房间相连的通道中等概率随机选一条走,求逃离迷宫所需要走的通道数的期望值(如果不能逃离输出impossible)。

做法:求期望采用逆推的方式。设f[i]表示从房间i开始走,逃离迷宫所需要走的通道数的期望值,令fa[i]为点i的父亲(整棵树以1为根时),deg[i]为点i的度数,我们知道对于每个叶子节点有:f[i]=k[i]*f[1]+(1-k[i]-e[i])*(f[fa[i]]+1),对于每个节点有:f[i]=k[i]*f[1]+(1-k[i]-e[i])/deg[i]*Σ(f[j]+1),其中j满足点i和点j之间有直接连边。我们可以发现,一个节点的期望值跟三个部分有关:点1的期望,父亲节点的期望,儿子节点的期望,而儿子节点的期望也和这三个部分有关,一直下到叶子节点,因为叶子节点没有儿子节点,所以我们可以把叶子节点作为突破口。我们可以将每个点的期望表示成这样一个式子:f[i]=x*f[1]+y*f[fa[i]]+z,显然对于叶子节点有:x=k[i],y=1-k[i]-e[i],z=1-k[i]-e[i]。然后对于其他节点,因为其儿子节点的父亲节点就是它本身,所以我们可以用待定系数法求出这个节点的期望式。在最后,我们可以求出f[1]的期望式,即f[1]=x*f[1]+y*f[fa[1]]+z,由于fa[1]没有意义,我们把它舍去,变化一下式子就可以得到:f[1]=z/(1-x),这就是我们要求的答案了。注意当x无限趋近于1时(|x-1|≤1e-9),f[1]无法解出,这时就输出impossible就可以了。

以下是本人代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#define eps 1e-9using namespace std;int T,n,first[10010],tot,fa[10010];double f1[10010],f2[10010],f3[10010],k[10010],e[10010]; //f1,f2,f3即上文提到的系数x,y,zstruct edge {int v,next;} E[20010];bool flag;void insert(int a,int b){  E[++tot].v=b,E[tot].next=first[a],first[a]=tot;}void treedp(int v){  double s=1,a;  f1[v]=f2[v]=f3[v]=0;  for(int i=first[v];i;i=E[i].next)    if (E[i].v!=fa[v]){  fa[E[i].v]=v;  treedp(E[i].v);  f1[v]+=f1[E[i].v];  f2[v]+=f2[E[i].v];  f3[v]+=f3[E[i].v];  s+=1.0;}  if (v==1) s-=1.0;  f1[v]=f1[v]*(1-k[v]-e[v])/s;  f2[v]=f2[v]*(1-k[v]-e[v])/s;  f3[v]=f3[v]*(1-k[v]-e[v])/s;  a=1-f2[v];  f1[v]+=k[v];  f2[v]=(1-k[v]-e[v])/s;  f3[v]+=(1-k[v]-e[v]);  f1[v]/=a,f2[v]/=a,f3[v]/=a;}int main(){  scanf("%d",&T);  for(int t=1;t<=T;t++)  {    scanf("%d",&n);memset(first,0,sizeof(first));tot=0;for(int i=1,a,b;i<n;i++){  scanf("%d%d",&a,&b);  insert(a,b),insert(b,a);}for(int i=1;i<=n;i++){  scanf("%lf%lf",&k[i],&e[i]);  k[i]/=100.0,e[i]/=100.0;}fa[1]=0;treedp(1);if (fabs(f1[1]-1)<=eps) printf("Case %d: impossible\n",t);else printf("Case %d: %.6lf\n",t,f3[1]/(1-f1[1]));  }    return 0;}


0 0
原创粉丝点击