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(){;}
只要是活着的东西,就算是神我也杀给你看。