BZOJ 3566: [SHOI2014]概率充电器 概率dp

本文详细解析了一种树形概率动态规划算法,介绍了如何正确计算节点间的概率,并提供了一个具体的实现示例。此外,还讨论了一种求解节点不可充电概率的更优解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:点击打开链接

树形概率dp,刚开始以为每个点的概率应该是其他点对其概率贡献加和,然后WA

看了题解才明白并不是,两个事件的并事件的概率应为

P(a | b) = P(a) + P(b) - P(ab)

独立事件 P(ab) = P(a) * P(b)

举个样例

3

1 2 50

1 3 50

0 1 1

并不能认为1充电的概率是1的

求概率的时候把直接加换成上式就可以了

#include<bits/stdc++.h>
using namespace std;
struct node{
	int ne;
	double cost;
	double pp;
	node(int u, double v){
		ne = u;
		cost = v;
		pp = 0;
	}
	node(){
		
	}
};
const int maxn = 5e5 + 10;
double p[maxn], ans = 0, pself[maxn];
vector<node>w[maxn];
double ADD(double a1, double a2){
	return a1 + a2 - a1 * a2;
}
double dfs1(int fa, int x){
	double p1 = 0;
	for(int i = 0; i < w[x].size(); i++){
		if(w[x][i].ne == fa)
		continue;
		w[x][i].pp = w[x][i].cost * dfs1(x, w[x][i].ne);
		p1 = ADD(p1, w[x][i].pp);
	}
	p[x] = p1;
	return ADD(p1, pself[x]);
}
void dfs2(int fa, double fp, int x){
	ans += ADD(fp, ADD(p[x], pself[x])); 
//	cout << x << " " << fp + p[x] + pself[x] << endl;
	for(int i = 0; i < w[x].size(); i++){
		if(w[x][i].ne == fa)
		continue;
		double temp1;
		if(fabs(1 - w[x][i].pp) <= 1e-9) //这里没判除零改了很长时间
		temp1 = 0;
		else
		temp1 = (p[x] - w[x][i].pp) / (1 - w[x][i].pp);
		dfs2(x, (ADD(temp1, ADD(pself[x], fp))) * w[x][i].cost, w[x][i].ne);
	}
	return ;
}
int main(){
	int n, a, b;
	double pp;
	cin >> n;
	for(int i = 1; i < n; i++){
		scanf("%d %d %lf", &a, &b ,&pp);
		node u1(b, pp / 100.0);
		node u2(a, pp / 100.0);
		w[a].push_back(u1);
		w[b].push_back(u2);
	}
	for(int i = 1; i <= n; i++){
		scanf("%lf", &pp);
		pself[i] = pp / 100.0;
	}
	dfs1(0, 1);
//	for(int i = 1; i <= n; i++){
//		cout << i << ":" << p[i] << endl;
//	}
	dfs2(0, 0, 1);
	printf("%.6lf\n", ans);
	return 0;
}

还有一种更优秀的方法是求每个点不能充电的概率,这个概率其实就是每个点不能给这个节点充电的概率和

这样精度肯定比上诉方法优秀,写起来也简单。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值