BZOJ3566 概率充电器 概率dp

哼我就要正着推

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3566

 

题意:节点有没有电看脸,线好不好看脸,问一个正常的亚洲人会给几个东西充上电。

我就正着推了怎么地首先,我们定义一下数组含义,$f[x]$表示这个点有电的概率,$g[x]$表示这个点被自己和儿子充上电的概率。

【普及选修2-3知识】

概率的可加性:$P(X∨Y)=P(X)+P(Y)-P(X∧Y)$。

那么这样$g[x]$就很好推了:$g[x]=g[没有v的x概率]+g[v]*l-g[没有v的x概率]*g[v]*l$,其中,$l$表示两点间连线带电概率。这个一遍从下到上搞上去就好了。

问题在于这个$f[x]$上。首先$f[x]$一定包括$g[x]$,另外还有一部分是他的爸爸给他充上了电的概率,这就是我们接下来需要求的。

首先我们可以肯定根节点$f[root]=g[root]$。

接下来,我们再次考虑$f[x]$的求法:$f[x]=f[没有v的x]+g[v]*l-f[没有v的x]*g[v]*l$,然后我们使用高深的数学知识移项得到$f[x]-g[v]*l=f[没有v的x]*(1-g[v]*l)$,就可以得到爸爸没有这个儿子有电的概率,然后儿子的$f[v]$就是:$f[v]=g[v]+((f[x]-g[v]*l)/(1-g[v]*l))*l-g[v]*((f[x]-g[v]*l)/(1-g[v]*l))*l$

啊好麻烦我后悔了(躺倒在沙滩上的一条咸鱼)(大概这就是做这道题每个正着推的人的心路历程)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=500005;
 8 const double eps=1e-8;
 9 struct node
10 {
11     int from,to,next;long double dis;
12     node(){;}
13     node(int u,int v,long double w,int x):from(u),to(v),dis(w),next(x){;}
14 }edge[maxn<<1];
15 int head[maxn],tot;
16 void addedge(int u,int v,long double w)
17 {
18     edge[++tot]=node(u,v,w,head[u]);head[u]=tot;
19 }
20 int n,pa[maxn];
21 long double f[maxn],g[maxn],p[maxn];
22 void dfs1(int root,int fa)
23 {
24     pa[root]=fa;g[root]=p[root];
25     for(int i=head[root];i;i=edge[i].next)
26     {
27         int v=edge[i].to;
28         if(v!=fa)
29         {
30             dfs1(v,root);
31             long double tmp=g[v]*edge[i].dis;
32             g[root]=g[root]+tmp-g[root]*tmp;
33         }
34     }
35 }
36 long double ans;
37 void dfs2(int root)
38 {
39     ans+=f[root];
40     for(int i=head[root];i;i=edge[i].next)
41     {
42         int v=edge[i].to;
43         if(v!=pa[root])
44         {
45             long double tmp=g[v]*edge[i].dis,temp=fabs(1-tmp)<=eps?1:(f[root]-tmp)/(1-tmp),tmp2=temp*edge[i].dis;
46             f[v]=g[v]+tmp2-g[v]*tmp2;
47             dfs2(v);
48         }
49     }
50 }
51 int haha()
52 {
53     scanf("%d",&n);
54     for(int i=1;i<n;i++)
55     {
56         int x,y;double z;scanf("%d%d%lf",&x,&y,&z);long double dis=z/100.0;
57         addedge(x,y,dis);addedge(y,x,dis);
58     }
59     for(int i=1;i<=n;i++){double x;scanf("%lf",&x);p[i]=x/100.0;}
60     dfs1(1,0);f[1]=g[1];dfs2(1);
61     printf("%0.6lf\n",(double)ans);
62 }
63 int sb=haha();
64 int main(){;}
BZOJ3566

 

posted @ 2017-09-13 21:35  ccc000111  阅读(260)  评论(0编辑  收藏  举报