zoukankan      html  css  js  c++  java
  • hdu 4035 Maze 概率DP

        题意:
        有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,
        从结点1出发,开始走,在每个结点i都有3种可能:
            1.被杀死,回到结点1处(概率为ki)
            2.找到出口,走出迷宫 (概率为ei)
            3.和该点相连有m条边,随机走一条
        求:走出迷宫所要走的边数的期望值。
    思路:
        设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望。E[1]即为所求。

        叶子结点:有3种情况:kill ;exit(成功出去的期望为0) ;回到父节点。
        E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);
             = 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则无解...

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4035
    代码如下:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<iomanip>
     5 #include<cmath>
     6 #include<cstring>
     7 #include<vector>
     8 #define ll __int64
     9 #define pi acos(-1.0)
    10 #define MAX 10005
    11 using namespace std;
    12 vector<int>p[MAX];
    13 double A[MAX],B[MAX],C[MAX],k[MAX],e[MAX];
    14 bool dfs(int n,int f)
    15 {
    16     int m=p[n].size();
    17     double d=1-k[n]-e[n];
    18     A[n]=k[n];
    19     B[n]=d/m;
    20     C[n]=d;
    21     if(m==1&&f!=-1) return true;
    22     double temp=0.0;
    23     for(int i=0;i<m;i++){
    24         int v=p[n][i];
    25         if(v==f) continue;
    26         if(!dfs(v,n)) return false;
    27         A[n]+=B[n]*A[v];
    28         C[n]+=B[n]*C[v];
    29         temp+=B[n]*B[v];
    30     }
    31     temp=1-temp;
    32     if(temp<=1e-9) return false;
    33     A[n]/=temp;
    34     B[n]/=temp;
    35     C[n]/=temp;
    36     return true;
    37 }
    38 int main(){
    39     int t,i,n,a,b,c=0;
    40     scanf("%d",&t);
    41     while(t--){
    42         scanf("%d",&n);
    43         for(i=1;i<=n;i++) p[i].clear();
    44         for(i=1;i<n;i++){
    45             scanf("%d%d",&a,&b);
    46             p[a].push_back(b);
    47             p[b].push_back(a);
    48         }
    49         for(i=1;i<=n;i++){
    50             scanf("%lf%lf",&k[i],&e[i]);
    51             k[i]/=100.0;
    52             e[i]/=100.0;
    53         }
    54         printf("Case %d: ",++c);
    55         if(dfs(1,-1)&&fabs(1-A[1])>1e-9)
    56             printf("%.6lf
    ",C[1]/(1-A[1]));
    57         else printf("impossible
    ");
    58     }
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    第五节13读取配置中的连接字符串 简单
    第五节 8_手机归属地查询案例 简单
    第五节 8登陆练习操作 简单
    第五节 21类型化DataSet 简单
    PHP XML操作类DOMDocument 简单
    第十节 1ASP.Net简介及学习方法 简单
    第五节 8注入漏洞与参数化查询 简单
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误............ 简单
    第五节 17DateStr 简单
    第五节 19可空数据类型 简单
  • 原文地址:https://www.cnblogs.com/xin-hua/p/3246174.html
Copyright © 2011-2022 走看看