HDU4035 Maze(期望DP)
程序员文章站
2022-03-12 18:34:29
题意 抄袭自https://www.cnblogs.com/Paul-Guderian/p/7624039.html 有n个房间,由n-1条隧道连通起来,形成一棵树,从结点1出发,开始走,在每个结点i都有3种可能(概率之和为1):1.被杀死,回到结点1处(概率为ki)2.找到出口,走出迷宫 (概率为 ......
题意
抄袭自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$个位置走出迷宫的期望步数。
转移方程分叶子节点和父亲节点讨论一下,发现都可以化成$f[x] = a f[1] + b f[fa] + c$的形式
然后直接递推系数即可
具体可以看https://www.cnblogs.com/paul-guderian/p/7624039.html
/* */ #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<vector> #include<set> #include<queue> #include<cmath> #define pair pair<int, int> #define mp(x, y) make_pair(x, y) #define fi first #define se second //#define int long long //#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? eof : *p1++) //char buf[(1 << 22)], *p1 = buf, *p2 = buf; using namespace std; const int maxn = 1e5 + 10, inf = 1e9 + 10; const double eps = 1e-10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n; vector<int> v[maxn]; double b[maxn], e[maxn], a[maxn], b[maxn], c[maxn]; bool dcmp(double x) { if(fabs(x) < eps) return 0; else return 1; } void init() { for(int i = 1; i <= n; i++) v[i].clear(); } double get(int x) { return (1 - b[x] - e[x]) / (v[x].size()); } bool dfs(int x, int fa) { if(v[x].size() == 1 && (v[x][0] == fa)) {a[x] = b[x], c[x] = b[x] = get(x); return 1;} double as = 0, bs = 0, cs = 0; for(int i = 0; i < v[x].size(); i++) { int to = v[x][i]; if(to == fa) continue; if(!dfs(to, x)) return 0; as += a[to]; bs += b[to]; cs += c[to] + 1; } double p = get(x); double d = (1 - bs * p); if(!dcmp(d)) return 0; a[x] = (b[x] + as * p) / d; b[x] = p / d; c[x] = (cs * p + ((x == 1) ? 0 : p)) / d; return 1; } int main() { int t = read(); for(int gg = 1; gg <= t; gg++) { n = read(); init(); //printf("%d ", v[3].size()); for(int i = 1; i <= n - 1; i++) { int x = read(), y = read(); v[x].push_back(y); v[y].push_back(x); } for(int i = 1; i <= n; i++) b[i] = (double) read() / 100, e[i] = (double) read() / 100; if(dfs(1, 0) && (dcmp(1 - a[1]))) printf("case %d: %.10lf\n", gg, c[1] / (1 - a[1])); else printf("case %d: impossible\n", gg); } return 0; } /* */
推荐阅读
-
洛谷P3600 随机数生成器(期望dp 组合数)
-
HDU4418 Time travel(期望dp 高斯消元)
-
HDU4089 Activation(困难的循环期望dp)
-
POJ2096 Collecting Bugs(期望dp)
-
cf643E. Bear and Destroying Subtrees(期望dp)
-
Puzzles【Codeforces 697 D】【树形DP + 期望DP】
-
Beautiful Mirrors【Codeforces 1265 E】【期望DP】
-
算法——期望DP
-
2018.08.30【SCOI2017】D2T1 花园 (期望DP)
-
cf1097D. Makoto and a Blackboard(期望dp)