[题解]HDU4035 Maze

题目描述

一棵\(n\)个节点的树,从1号结点开始游戏,在每一个点\(x\):

  • 有\(a[x]/100\)的可能掉进陷阱死翘翘回到1重新开始
  • 有\(b[x]/100\)的可能找到出口并结束游戏
  • 剩下的可能中,你等概率随机选一条和它相连的边(可以是父亲)走过去

问期望多少步结束游戏

\(1\leq T \leq 30,1\leq n \leq 10000\)

分析

设\(dp[x]\)表示位于\(x\)节点时,期望走几步才能结束游戏

那么\(dp[x]=0.01a[x]*dp[1]+0.01b[x]*0+0.01(1-a[x]-b[x])*(\frac{1}{cnt}(\sum dp[son]+dp[1]+1))\)

看了一下数据范围发现并不能承受高斯消元的时间复杂度

我们发现,每一个点的\(dp\)值之和父亲、1号点还有儿子有关,那么叶子节点的\(dp\)值可以用父亲和1号点表示,这样往上代,合并同类项之后可以发现,每一个点的值都可以表示为:

\(dp[x]=...*dp[1]+...*dp[fa[x]]+...\)(常数项)

所以只需要维护一下每一项的系数就可以\(O(n)\)求解了,记得特判Impossible

代码

void SEARCH(int x,int pa){
    f[x][0]=f[x][1]=f[x][2]=0;
    int cnt=0;
    for(int r=lst[x];r;r=nxt[r]){
        cnt++;
        if(edge[r]==pa)continue;
        SEARCH(edge[r],x);
    }
    DB lef=(100-a[x]-b[x])*0.01;
    DB hlp=0;
    for(int r=lst[x];r;r=nxt[r]){
        if(edge[r]==pa)continue;
        int pos=edge[r];
        f[x][0]+=f[pos][0];
        f[x][2]+=f[pos][2];
        hlp+=f[pos][1];
    }
    f[x][0]=(lef*f[x][0])/(1.0*cnt)+a[x]*0.01;
    f[x][2]=(lef*f[x][2])/(1.0*cnt)+lef;
    if(x==1)f[x][1]=0;else f[x][1]=lef/(1.0*cnt);
    hlp=hlp*lef/(1.0*cnt);
    hlp=1.0-hlp;
    if(x==1)hlp-=f[x][0];
    if(hlp<=0)f[x][0]=f[x][1]=f[x][2]=0;
    else rep(i,0,2)f[x][i]/=hlp;
}

原文地址:https://www.cnblogs.com/SCL123/p/11831202.html

时间: 2024-11-08 20:32:43

[题解]HDU4035 Maze的相关文章

[hdu4035] Maze【概率dp 数学期望】

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4035 真的是一道好题,题解比较麻烦,我自己在纸上写了好大一块草稿才搞出来,不用公式编辑器的话就很难看清楚,所以不上题解啦,贴一个题解的链接:http://blog.csdn.net/balloons2012/article/details/7891054 注意此题卡精度,我一开始eps是1e-8,WA掉了,开到了1e-10,AC~,真是烦卡精度的题. #include <cstdio> #inclu

[hdu4035]Maze——树上高消

题目大意: 给定一颗树,从1号节点开始,在每个节点都有三种可能: 1.以\(k_i\)的概率回到1号节点 2.以\(e_i\)的概率走出迷宫 3.和该点相连的边随机走一条 求走出迷宫期望下走的步数. 思路: 首先设\(p_i=1-k_i-e_i\). 设从第\(i\)个点出发,期望意义下走出迷宫需要走的步数为\(f_i\),那么我们得到的递推式是: \[ f_i=k_i\times f_1+p_i\times (1+\frac{f_{fa}+\sum_vf_v}{d_i}) \] 不难发现这个递

HDU-4035 Maze (概率DP求期望)

题目大意:在一个树形迷宫中,以房间为节点.有n间房间,每间房间存在陷阱的概率为ki,存在出口的概率为ei,如果这两种情况都不存在(概率为pi),那么只能做出选择走向下一个房间(包括可能会走向上一个房间).根节点为1,当遇到陷阱时必须返回到根节点1处重新开始,当遇到出口时,走出迷宫.问从开始到走出迷宫所做出选择次数的期望值. 题目分析:定义状态dp(i)表示在节点 i 处直到走出迷宫的选择次数期望值.则状态转移方程为: dp(i)=ki*dp(1)+(1/m)*pi*∑(dp(son)+1) (i

HDU4035 Maze(期望DP)

题意 抄袭自https://www.cnblogs.com/Paul-Guderian/p/7624039.html 有n个房间,由n-1条隧道连通起来,形成一棵树,从结点1出发,开始走,在每个结点i都有3种可能(概率之和为1):1.被杀死,回到结点1处(概率为ki)2.找到出口,走出迷宫 (概率为ei)3.和该点相连有m条边,随机走一条求:走出迷宫所要走的边数的期望值.(2≤n≤10000) Sol 非常nice的一道题. 我简单的说一下思路:首先列出方程,$f[i]$表示在第$i$个位置走出

HDU4035 Maze 【树形DP】【期望DP】

题目分析: 以前一直不会这个方法, 我好菜啊. 转移分为三个部分,一个是直接成功,一个是转移到E1,还有一个是转移到自己周围的一圈儿点. 如果是叶子那么只能转移到父亲,如果不是叶子可以把非叶子的转移代换,这样也只转移到父亲,判一下无解就行了. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 10200; 5 const double eps = 1e-10; 6 7 int n,Tmp,cas;

题解 CF1292A 【NEKO&#39;s Maze Game】

有一个结论: 当 \((1,1)\) 不能抵达 \((2,n)\) 时,必定存在一个点对,这两个点的值均为真,且坐标中的 \(x\) 互异,\(y\) 的差 \(\leq 1\) 这个结论的正确性感觉非常显然,就不多说了. 下图可以形象地解释点对的位置关系. 那对于每个点的值,只要开一个数组 f[i][j] 记录一下即可. 有了上述结论,我们记一个变量 \(cnt\) 表示 " 有多少对满足上述结论的点对 " ,则 \(cnt=0\) 时,\((1,1)\) 可以抵达 \((2,n)\

【HDU4035】Maze

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <vector> 6 #include <cmath> 7 8 using namespace std; 9 const int maxn=10000+100; 10 int T,n; 11 double E[maxn],K[maxn],A[m

【luogu P1825 [USACO11OPEN]玉米田迷宫Corn Maze】 题解

题目链接:https://www.luogu.org/problemnew/show/P1825 带有传送门的迷宫问题 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 2001; char map[maxn][maxn]; int fx[4] = {0, 1, 0, -1};

HDU 1045 Fire Net 二分图Bipartite题解

本题可以使用DFS直接爆搜出答案,不过这样类型的题目其实是个二分图的题解. 这个二分图,难不在Hungary算法,而是难在于建图.需要挺高的抽象思维的. 建图: 1 把同一行不被X分开的格子标同一个号码,被X分开的标下一个号码,这样做是为了缩点,不需要把所有的格子都分开标号,而且可以更方便建个更加小的图. 2 同理把同一列的格子标号 3 然后判断相同一个格子的行标号和列标号是有路径的,其他不在同一个格子的都是没有路径的. 4 这样就等于以行标号和列标号作为左右顶点,构建成一个二分图了 然后使用H