HDU 4035 Maze 概率dp 难度:2

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

求步数期望,设E[i]为在编号为i的节点时还需要走的步数,father为dfs树中该节点的父节点,son为dfs树种该节点的子节点的集合,kl[i]为被杀掉的概率,ex[i]为逃出的概率

mv[i]=(1-kl[i]-ex[i])/(1+len(son))

则明显

E[i]=(E[father]+1)*mv[i]+sigma((E[son]+1)*mv[i])+E[1]*K[i]

未知量是E[i],E[father],E[1]

对于叶节点,设E0[i]为该公式中E[1]的系数,EE[i]为该公式中的常数项,EF[i]为E[father]的系数,则可以用这三个值表示E[i]

对于非叶节点,从E[son]中可以得到son的E0,EE,EF,另设ES[i]为E[i]在儿子中积累的系数,则

EF[i]:mv[i]

ES[i]:(由儿子积累来的)sigma(EF[son]*mv[i])

EE[i]:1-kl[i]-ex[i]+sigma(EE[son]*mv[i])

E0[i]:kl[i]+sigma(E0[son]*mv[i])

计算完了之后再EE,E0,EF都除以(1-ES[i]),ES[i]为1当然就不能走出这个迷宫了

这样到了1这个节点就是E[1]=EE[1]/(1-ES[1]-E0[1])

一开始以为exit时应该有E[i]=ex[i]*E[i]+(E[father]+1)*mv[i]+sigma((E[son]+1)*mv[i])+E[1]*K[i],这里思想卡住了,实际上应该是ex[i]*0

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 1e4+4;
const double eps = 1e-10;
int n;
double kl[maxn],ex[maxn],mv[maxn];//kill exit move
int first[maxn],deg[maxn];
int dcmp(double a,double b){
    if(fabs(a-b)<eps)return 0;
    return a>b?1:-1;
}

struct edge{
    int f,t,nxt;
}e[maxn*2];
void addedge(int f,int t,int ind){
    e[ind].nxt=first[f];
    e[ind].t=t;
    e[ind].f=f;
    first[f]=ind;
}
void input(){
    memset(first,-1,sizeof first);
    memset(deg,0,sizeof deg);
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int f,t;
        scanf("%d%d",&f,&t);
        addedge(f,t,2*i);
        addedge(t,f,2*i+1);
        deg[f]++;
        deg[t]++;
    }
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",kl+i,ex+i);
        kl[i]/=100;ex[i]/=100;
        if(deg[i])mv[i]=(1-ex[i]-kl[i])/deg[i];
    }
}

double ef[maxn],es[maxn],e0[maxn],ee[maxn];
bool dfs(int s,int father){
    ef[s]=mv[s];
    //es[s]=ex[s];
    e0[s]=kl[s];
    ee[s]=1-kl[s]-ex[s];
    for(int p=first[s];p!=-1;p=e[p].nxt){
        int t=e[p].t;
        if(t==father)continue;
        if(!dfs(t,s))return false;
        es[s]+=ef[t]*mv[s];
        e0[s]+=e0[t]*mv[s];
        ee[s]+=ee[t]*mv[s];
    }
    if(dcmp(es[s],1)!=0&&s!=1){
        e0[s]/=(1-es[s]);
        ef[s]/=(1-es[s]);
        ee[s]/=(1-es[s]);
    }
    return true;
}
double calc(){
    memset(ee,0,sizeof ee);
    memset(ef,0,sizeof ef);
    memset(es,0,sizeof es);
    memset(e0,0,sizeof e0);

    if(!dfs(1,-1)||dcmp(e0[1]+es[1],1)==0)return -1;
    return ee[1]/(1-e0[1]-es[1]);
}
int main(){
    int T;
    scanf("%d",&T);
    for(int ti=1;ti<=T;ti++){
        input();
        double ans=calc();
        if(ans>-eps) printf("Case %d: %.6f\n",ti,ans);
        else printf("Case %d: impossible\n",ti);
    }
    return 0;
}
时间: 2024-11-08 20:57:09

HDU 4035 Maze 概率dp 难度:2的相关文章

HDU 4035 Maze 概率DP 好题

Maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 2012    Accepted Submission(s): 802Special Judge Problem Description When wake up, lxhgww find himself in a huge maze. The maze consisted by

hdu 4035 Maze (概率DP)

Maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 1713    Accepted Submission(s): 659 Special Judge Problem Description When wake up, lxhgww find himself in a huge maze. The maze consisted b

HDU 4035 Maze 概率dp+树形dp

题解:点击打开链接 #include <cstdio> #include <iostream> #include <cstring> #include <queue> #include <algorithm> #include <map> #include <cmath> using namespace std; const double eps = 1e-9; const int N = 10010; vector<

HDU 4035Maze(概率DP)

HDU 4035   Maze 体会到了状态转移,化简方程的重要性 题解转自http://blog.csdn.net/morgan_xww/article/details/6776947 /** dp求期望的题. 题意: 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结点i都有3种可能: 1.被杀死,回到结点1处(概率为ki) 2.找到出口,走出迷宫 (概率为ei) 3.和该点相连有m条边,随机走一条 求:走出迷宫所要走的边数的期望值. 设 E[i]表示

hdu 4870 Rating(概率DP&amp;高数消元)

Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 714    Accepted Submission(s): 452 Special Judge Problem Description A little girl loves programming competition very much. Recently, she

HDU 3853 LOOPS (概率dp)

LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Total Submission(s): 2931    Accepted Submission(s): 1209 Problem Description Akemi Homura is a Mahou Shoujo (Puella Magi/Magical Girl). Homura wants to help

HDU 4089 Activation (概率dp 好题 + 难题)

Activation Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1842    Accepted Submission(s): 689 Problem Description After 4 years' waiting, the game "Chinese Paladin 5" finally comes out.

HDU - 1099 - Lottery - 概率dp

http://acm.hdu.edu.cn/showproblem.php?pid=1099 最最简单的概率dp,完全是等概率转移. 设dp[i]为已有i张票,还需要抽几次才能集齐的期望. 那么dp[n]=0,因为我们已经集齐了. \[dp[i]=(\frac{i}{n}*dp[i]+\frac{n-i}{n}*dp[i+1])+1\] 移项得答案. 然后写个分数类,注意约分. #include<bits/stdc++.h> using namespace std; typedef long

HDU 4599 Dice (概率DP+数学+快速幂)

题意:给定三个表达式,问你求出最小的m1,m2,满足G(m1) >= F(n), G(m2) >= G(n). 析:这个题是一个概率DP,但是并没有那么简单,运算过程很麻烦. 先分析F(n),这个用DP来推公式,d[i],表示抛 i 次连续的点数还要抛多少次才能完成.那么状态转移方程就是 d[i] = 1/6*(1+d[i+1]) + 5/6*(1+d[1]), 意思就是说在第 i 次抛和上次相同的概率是1/6,然后加上上次抛的和这一次,再加上和上次不同的,并且又得从第1次开始计算. 边界就是