zoukankan      html  css  js  c++  java
  • hdu4035 Maze (树上dp求期望)

     dp求期望的题。
        题意:
        有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,
        从结点1出发,开始走,在每个结点i都有3种可能:
            1.被杀死,回到结点1处(概率为ki)
            2.找到出口,走出迷宫 (概率为ei)
            3.和该点相连有m条边,随机走一条
        求:走出迷宫所要走的边数的期望值。
    
        设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望。E[1]即为所求。
    
        叶子结点:
        E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);//因为是到达,i点跑出去的期望步数,所以逃出去的那个概率应该乘以0
             = ki*E[1] + (1-ki-ei)*E[father[i]] + (1-ki-ei);
    
        非叶子结点:(m为与结点相连的边数)
        E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );
             = ki*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei)/m*∑(E[child[i]]) + (1-ki-ei);
    
        设对每个结点:E[i] = Ai*E[1] + Bi*E[father[i]] + Ci;
    
        对于非叶子结点i,设j为i的孩子结点,则
        ∑(E[child[i]]) = ∑E[j]
                       = ∑(Aj*E[1] + Bj*E[father[j]] + Cj)
                       = ∑(Aj*E[1] + Bj*E[i] + Cj)
        带入上面的式子得
        (1 - (1-ki-ei)/m*∑Bj)*E[i] = (ki+(1-ki-ei)/m*∑Aj)*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei) + (1-ki-ei)/m*∑Cj;
        由此可得
        Ai =        (ki+(1-ki-ei)/m*∑Aj)   / (1 - (1-ki-ei)/m*∑Bj);
        Bi =        (1-ki-ei)/m            / (1 - (1-ki-ei)/m*∑Bj);
        Ci = ( (1-ki-ei)+(1-ki-ei)/m*∑Cj ) / (1 - (1-ki-ei)/m*∑Bj);
    
        对于叶子结点
        Ai = ki;
        Bi = 1 - ki - ei;
        Ci = 1 - ki - ei;
    
        从叶子结点开始,直到算出 A1,B1,C1;
    
        E[1] = A1*E[1] + B1*0 + C1;
        所以
        E[1] = C1 / (1 - A1);
        若 A1趋近于1则无解...
    上面这一问题,中发现E[1]消不去,然后就用算出A,B,C的方式来求解。
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<vector>
     7 using namespace std;
     8 const int MAXN=10007;
     9 const double eps=1e-10;//这里1e-8会WA。设为1e-9和1e-10可以
    10 double k[MAXN],e[MAXN];
    11 double A[MAXN],B[MAXN],C[MAXN];
    12 
    13 int T,n,u,v,iCase;
    14 vector<int>vec[MAXN];//存树
    15 
    16 bool dfs(int t,int pre)//t的根结点是pre
    17 {
    18     int m=vec[t].size();//点t的度
    19     A[t]=k[t];
    20     B[t]=(1-k[t]-e[t])/m;
    21     C[t]=1-k[t]-e[t];
    22     double tmp=0;
    23     for(int i=0;i<m;i++)
    24     {
    25         int v=vec[t][i];
    26         if(v==pre)continue;
    27         if(!dfs(v,t))return false;
    28         A[t]+=(1-k[t]-e[t])/m*A[v];
    29         C[t]+=(1-k[t]-e[t])/m*C[v];
    30         tmp+=(1-k[t]-e[t])/m*B[v];
    31     }
    32     if(fabs(tmp-1)<eps)return false;
    33     A[t]/=(1-tmp);
    34     B[t]/=(1-tmp);
    35     C[t]/=(1-tmp);
    36     return true;
    37 }
    38 int main()
    39 {
    40     scanf("%d",&T);
    41     while(T--)
    42     {
    43         iCase++;
    44         scanf("%d",&n);
    45         for(int i=1;i<=n;i++)vec[i].clear();
    46         for(int i=1;i<n;i++)
    47         {
    48             scanf("%d%d",&u,&v);
    49             vec[u].push_back(v);
    50             vec[v].push_back(u);
    51         }
    52         for(int i=1;i<=n;i++)
    53         {
    54             scanf("%lf%lf",&k[i],&e[i]);
    55             k[i]/=100;
    56             e[i]/=100;
    57         }
    58         printf("Case %d: ",iCase);
    59         if(dfs(1,-1)&&fabs(1-A[1])>eps)
    60         {
    61             printf("%.6lf
    ",C[1]/(1-A[1]));
    62         }
    63         else printf("impossible
    ");
    64     }
    65 }
     
  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7673939.html
Copyright © 2011-2022 走看看