最怕你一生庸碌无为,却总是安慰自己|

Mr_KaYa

园龄:2年7个月粉丝:2关注:2

数学期望DP学习笔记

数学期望: 在概率论和统计学中,数学期望(mathematic expectation)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小。——摘自百度百科
不懂?太正常了,百度百科就是不写人话。
举个栗子解释一下:在一次膜你赛中,小 z 预估自己有 0.5 的概率考 300 分,0.3 的概率考250分,0.2 的概率考 200分,计算方法与加权平均值有些类似,那她得分的数学期望即是: 0.5×300+0.3×250+0.2×200=265pts
具体地,记第 i 种结果的概率为 pi,结果得分为 fi,那么 x 的期望 E(x)=i=1xpi×fi
注意,i=1xpi=1,即所有概率总和必须是 1


Problem1 P4316 绿豆蛙的归宿
题意简述
给出一张 DAG,保证连通图,随机行走,求 1n 的路径长度期望。具体地,若当前在点 u,出边数为 odu,则走到每一条出边的概率相等,都为 1odu
题目解析
我们设 fi 表示从 1i 的路径长度期望,答案显然是 fn
但手算样例,我们看到如下情况,f1 显然为 0f2 易得为 0.5f3 如何计算?
p9LHnqH.png
显然我们还需要考虑从 13 的概率。但我们感觉这种方法略微繁琐,正推不方便,不妨逆推,也就是设 fi 表示从 in 的路径长度期望,此时答案为 f1,初始状态 fn=0
可以得出转移方程,当前在点 ufu=1odu×fv+wu,v
实现中,我们要逆推,所以两种方法处理图:记忆化搜索或者建反图拓扑排序。
代码实现
1. 记忆化搜索

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n,m;
int x,y;
double z;
struct edge{int v,next;double w;}e[N<<1];
int head[N],tot;
inline void add(int u,int v,double w){e[++tot].v=v,e[tot].w=w,e[tot].next=head[u],head[u]=tot;}
double chu[N];
double f[N];

void dfs(int u){
	if(f[u]) return ;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].v;
		if(!f[v]) dfs(v);
		f[u]+=f[v]+e[i].w;
	}
	if(chu[u]) f[u]/=chu[u];
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i) scanf("%d%d%lf",&x,&y,&z),add(x,y,z),chu[x]++; 
	dfs(1);
	printf("%.2lf",f[1]);
	return 0;
}

2. 反图拓扑

#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+100;
const int M=2*N;
int n,m;
struct node{
	int ver,nxt;
	double edge;
}e[M];
int head[N],tot;
int in[N],out[N];
double f[N],g[N];
void add(int x,int y,double z){
	e[++tot]={y,head[x],z};
	head[x]=tot;
}
queue<int> q;
void topsort(){
	f[1]=0.0;
	g[1]=1.0;
	q.push(1);
	while(q.size()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=e[i].nxt){
			int y=e[i].ver;
			double z=e[i].edge;
			f[y]+=(f[x]+g[x]*z)/out[x];
			g[y]+=g[x]/out[x];
			in[y]--;
			if(in[y]==0){
				q.push(y);
			}
		}
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;
		double z;
		scanf("%d%d%lf",&x,&y,&z);
		add(x,y,z);
		in[y]++;
		out[x]++;
	}
	topsort();
	printf("%.2lf\n",f[n]);
	return 0;
}

(法 2 代码来自 此间的少年fu)。


Problem2 蓝桥杯 2022 省赛 A 组 E 题 (蓝桥杯终于出了个好题。)
题意简述
有一只虫想要爬上高度为 n 的树,初始位于树根, 即高度为 0,当它从高度 i1 爬到高度 i 时有 pi 的概率掉回树根, 求它从树根爬到树顶时,花费总时间的数学期望(一次尝试向上爬花费时间为 1)。
题目解析
类似的套路,我们设 fi 表示从 i 爬到 n 时间的数学期望,答案即为 f0
则从 i 成功上到 i+1 的概率是 1pi+1,掉回树根的概率 pi+1,初始状态 fn=0
易得:fi=1+(1pi+1)×fi+1+pi+1×f0
发现此时的 fifi+1f0 有关。有后效性的 DP?怎么办呢?
我们尝试多写几项寻找一下规律:
f0=1+(1p1)×f1+p1×f0
f1=1+(1p2)×f2+p2×f0
f2=1+(1p3)×f3+p3×f0
解方程组……高斯消元会 TLE……
于是直接代入可得 f0=1+(1p1)+(1p1)×(1p2)+(1p1)×(1p2)×(1p3)×fn+[p1+(1p1)×p2+(1p1)×(1p2)×p3]×f0

posted @   Mr_KaYa  阅读(63)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起