• 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 ");
        else printf("%.6f ",C/(1-A));
      }
    }

      

  • 相关阅读:
    结对编程:黄金点小游戏
    在win7环境下如何安装Microsoft Visual Studio
    软件工程第一次作业
    Android关于保存数据(Saving data)
    Android bitmap和canvas小记(转)
    java/android开发中删除文件
    博客园的第一篇
    安卓初学者必看实例,(计算圆面积)
    安卓初学者必看实例,(文件管理器简单实现)
    安卓初学者必看实例,(访问sqlite)
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/5571295.html
Copyright © 2020-2023  润新知