码迷,mamicode.com
首页 > 其他好文 > 详细

hdu4035(概率dp)

时间:2015-01-31 23:14:31      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:

 

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4035

题意:有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);
         = 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则无解...
技术分享
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-9
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
double A[N],B[N],C[N];
double k[N],e[N];
vector<int>g[N];
bool dfs(int u,int fa)
{
    int m=g[u].size();
    A[u]=k[u];
    B[u]=(1-k[u]-e[u])/m;
    C[u]=1-k[u]-e[u];
    double temp=0;
    for(int i=0;i<m;i++)
    {
        int v=g[u][i];
        if(v==fa)continue;
        if(!dfs(v,u))return false;
        A[u]+=(1-k[u]-e[u])/m*A[v];
        C[u]+=(1-k[u]-e[u])/m*C[v];
        temp+=(1-k[u]-e[u])/m*B[v];
    }
    if(fabs(1-temp)<eps)return false;
    A[u]/=(1-temp);
    B[u]/=(1-temp);
    C[u]/=(1-temp);
    return true;
}
int main()
{
    int T,n,u,v,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)g[i].clear();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf",&k[i],&e[i]);
            e[i]/=100;k[i]/=100;
        }
        printf("Case %d: ",cas++);
        if(dfs(1,-1)&&fabs(A[1]-1)>eps)
        {
            printf("%.6lf\n",C[1]/(1-A[1]));
        }
        else puts("impossible");
    }
}
View Code

 

hdu4035(概率dp)

标签:

原文地址:http://www.cnblogs.com/lienus/p/4264828.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!