HDU 4035:Maze 概率DP求期望(有环)

Maze

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4035

题意:

有N(2 ≤ N ≤ 10000)个房间和一堆双向边(不存在环),每个房间有ki和ei两个值,分别代表回到房间1和游戏结束的概率,求游戏结束时通过的边数的期望

 

题解:

一道很好很经典的求期望的题

设E[i]为以i为起点,直到游戏结束所通过边数的期望,则E[1]即所求答案

设fa代表父亲节点(由于不存在环,则图为一棵树,设1为根节点),∑ch代表所有孩子节点,size代表与这个房间直接相连的房间数,设X=1-ki-ei

可以推导出 E[i]=ki*E[1]+X*(1/size*(E[fa]+1/size*∑E[ch])+1)---公式1

设 E[i]=a[i]*E[1]+b[i]*E[fa]+c[i]

则 ∑E[ch]=∑(a[ch]*E[1]+b[ch]*E[i]+c[ch])

代入公式1可得 E[i]=( (ki+X/size*∑a[ch])*E[1]+X/size*∑E[fa]+X+X/size*∑(c[ch]) ) /(1-X/size*b[ch])

对比可得

  a[i]=(ki+X/size*∑a[ch])/(1-X/size*b[ch])

  b[i]=X/size/(1-X/size*b[ch])

  c[i]=(X+X/size*c[ch])/(1-X/size*b[ch])

E[1]=a[1]*E[1]+b[1]*E[fa]+c[1]=(a[1]*E[fa]+c[1])/(1-a[1])=c[1]/(1-a[1])

             

代码

#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
const int N=10005;
const double eps=1e-9;
vector<int>q[N];
bool mark[N];
int fa[N],out[N],que[N],head,tail;
double k[N],e[N],A,B,C;
void dfs(int x=1)
{
  bool leaf=true;
  double p=1-k[x]-e[x];
  mark[x]=true;
  int m=q[x].size();
  double a=0.0,b=0.0,c=0.0;
  for(int i=0;i<q[x].size();++i)
  {
    fa[q[x][i]]=x;
    if(!mark[q[x][i]])
    {
      leaf=false;
      dfs(q[x][i]);
      a+=A,b+=B,c+=C;
    }
  }
  if(leaf)
  {
    A=k[x];
    B=C=p;
  }
  else
  {
    A=(k[x]+p/m*a)/(1-p/m*b);
    B=p/m/(1-p/m*b);
    C=(p+p/m*c)/(1-p/m*b);
  }
}
int main()
{
  int T,n,x,y,leaf,w=0;
  scanf("%d",&T);
  while(T--)
  {
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    out[i]=0,mark[i]=false,q[i].clear();
    for(int i=1;i<n;++i)
    {
      scanf("%d%d",&x,&y);
      q[x].push_back(y);
      q[y].push_back(x);
    }
    for(int i=1;i<=n;++i)
    {
      scanf("%lf%lf",&k[i],&e[i]);
      k[i]/=100.0,e[i]/=100.0;
    }
    dfs();
    printf("Case %d: ",++w);
    if(fabs(1-A)<eps)printf("impossible\n");
    else printf("%.6f\n",C/(1-A));
  }
}

  

posted @ 2016-06-08 20:58  kiuhghcsc  阅读(218)  评论(0编辑  收藏  举报