Bzoj3566:[SHOI2014]概率充电器:概率dp
2016-06-12 21:21
375 查看
题目链接[SHOI2014]概率充电器
woc我的高考概率是怎么学的这么简单的概率公都忘了233
公式:设事件A,B,p为概率,则
p(A|B)=p(A)+p(B)-p(A&B)
意思是发生A或B事件之一的概率是发生A的概率+发生B的概率-A和B同时发生概率
那么一个点x有电的情况为1:自己给自己充上了电;2:子节点给他充上了电;3:父节点给他充上了电
设事件1的概率为p[x],那么1、2使得x有电的概率可以直接使用公式dfs求出来
现在考虑3,我们从父节点贡献到子节点时要把子节点贡献给父节点的贡献减去,公式变一下形即可算出
然后在正向用公式合并即可
注意除法的时候判断除数大小,被坑了
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
int n,m,tot=1,h[maxn];
struct edge{int to,next; double w;}G[maxn*2];
double p[maxn],dp[maxn];
void dfs1(int x,int fat){
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fat) continue;
dfs1(v,x);
p[x]=p[x]+p[v]*G[i].w-p[x]*p[v]*G[i].w;//p(A|B)=p(A)+p(B)-p(A&B);
}
}
void dfs2(int x,int fat){
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fat) continue;
double tmp=1-p[v]*G[i].w;
if (abs(tmp)<1e-10) dp[v]=1;//这里要注意
else{
double tmp2=(dp[x]-p[v]*G[i].w)/tmp;
dp[v]=p[v]+tmp2*G[i].w-p[v]*tmp2*G[i].w;
}
dfs2(v,x);
}
}
void add(int x,int y,double z){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;
G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=z;
}
int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
int x,y; double z;
scanf("%d%d%lf",&x,&y,&z);
z/=100.0; add(x,y,z);
}
for (int i=1;i<=n;++i) scanf("%lf",&p[i]),p[i]/=100.0;
dfs1(1,-1); dp[1]=p[1]; dfs2(1,-1);
double ans=0;
for (int i=1;i<=n;++i) ans+=dp[i];
printf("%.6lf",ans);
}
woc我的高考概率是怎么学的这么简单的概率公都忘了233
公式:设事件A,B,p为概率,则
p(A|B)=p(A)+p(B)-p(A&B)
意思是发生A或B事件之一的概率是发生A的概率+发生B的概率-A和B同时发生概率
那么一个点x有电的情况为1:自己给自己充上了电;2:子节点给他充上了电;3:父节点给他充上了电
设事件1的概率为p[x],那么1、2使得x有电的概率可以直接使用公式dfs求出来
现在考虑3,我们从父节点贡献到子节点时要把子节点贡献给父节点的贡献减去,公式变一下形即可算出
然后在正向用公式合并即可
注意除法的时候判断除数大小,被坑了
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
int n,m,tot=1,h[maxn];
struct edge{int to,next; double w;}G[maxn*2];
double p[maxn],dp[maxn];
void dfs1(int x,int fat){
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fat) continue;
dfs1(v,x);
p[x]=p[x]+p[v]*G[i].w-p[x]*p[v]*G[i].w;//p(A|B)=p(A)+p(B)-p(A&B);
}
}
void dfs2(int x,int fat){
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fat) continue;
double tmp=1-p[v]*G[i].w;
if (abs(tmp)<1e-10) dp[v]=1;//这里要注意
else{
double tmp2=(dp[x]-p[v]*G[i].w)/tmp;
dp[v]=p[v]+tmp2*G[i].w-p[v]*tmp2*G[i].w;
}
dfs2(v,x);
}
}
void add(int x,int y,double z){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;
G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=z;
}
int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
int x,y; double z;
scanf("%d%d%lf",&x,&y,&z);
z/=100.0; add(x,y,z);
}
for (int i=1;i<=n;++i) scanf("%lf",&p[i]),p[i]/=100.0;
dfs1(1,-1); dp[1]=p[1]; dfs2(1,-1);
double ans=0;
for (int i=1;i<=n;++i) ans+=dp[i];
printf("%.6lf",ans);
}
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题