P4284 [SHOI2014]概率充电器 dp

这个题题干说的不清楚,一开始我以为只能是旁边紧挨着的传火,导致我一开始根本不知道哪错了。后来,我想到树形dp,但是需要正反考虑,()既要考虑父亲,又要考虑儿子),互相都有影响,所以没太想出来。后来知道两遍就行了,一遍考虑儿子,一遍考虑父亲,然后相乘就行了。

题干:

题目描述

著名的电子产品品牌SHOI 刚刚发布了引领世界潮流的下一代电子产品—— 概率充电器:

“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决 定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看 吧!”

SHOI 概率充电器由n-1 条导线连通了n 个充电元件。进行充电时,每条导 线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率 决定。随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行 间接充电。

作为SHOI 公司的忠实客户,你无法抑制自己购买SHOI 产品的冲动。在排 了一个星期的长队之后终于入手了最新型号的SHOI 概率充电器。你迫不及待 地将SHOI 概率充电器插入电源——这时你突然想知道,进入充电状态的元件 个数的期望是多少呢?
输入输出格式
输入格式:

第一行一个整数:n。概率充电器的充电元件个数。充电元件由1-n 编号。

之后的n-1 行每行三个整数a, b, p,描述了一根导线连接了编号为a 和b 的 充电元件,通电概率为p%。

第n+2 行n 个整数:qi。表示i 号元件直接充电的概率为qi%。

输出格式:

输出一行一个实数,为能进入充电状态的元件个数的期望,四舍五入到小 数点后6 位小数。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;++i)
#define lv(i,a,n) for(register int i = a;i >= n;--i)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
const int N = 5e5 + 5;
struct node
{
    int l,r,nxt;
    db w;
}a[N << 1];
int n,lst[N],len = 0;
int fa[N];
db q[N],g[N],f[N],p[N];
void add(int x,int y,db w)
{
    a[++len].l = x;
    a[len].r = y;
    a[len].w = w;
    a[len].nxt = lst[x];
    lst[x] = len;
}
void dfs(int u,int fat)
{
    fa[u] = fat;
    f[u] =  1 - q[u]; 
    for(int k = lst[u];k;k = a[k].nxt)
    {
        int y = a[k].r;
        if(y == fat) continue;
        dfs(y,u);
        f[u] *= (f[y] + (1 - f[y]) * (1 - a[k].w));
    }
}
void solve(int u)
{
    if(u == 1)
    {
        g[u] = 1;
    }
    for(int k = lst[u];k;k = a[k].nxt)
    {
        int y = a[k].r;
        if(y == fa[u]) continue;
        db P = g[u] * f[u] / (f[y] + (1 - f[y]) * (1 - a[k].w));
        g[y] = P + (1 - P) * (1 - a[k].w);
        solve(y);
    }
}
int main()
{
    read(n); 
    duke(i,1,n - 1)
    {
        int x,y,k;
        read(x);read(y);read(k);
        add(x,y,(db)k / (db)100);
        add(y,x,(db)k / (db)100);
    }
    duke(i,1,n)
    {
        int x;
        read(x);
        q[i] = (db)x / (db)100;
    }
    dfs(1,0);
    solve(1); 
    duke(i,1,n)
    {
        p[i] = 1 - f[i] * g[i];
    }
    db ans = 0;
    duke(i,1,n)
    {
        ans += p[i];
    }
    printf("%.6lf
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/DukeLv/p/10630551.html