概率期望问题总结

Posted 桂月二四

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了概率期望问题总结相关的知识,希望对你有一定的参考价值。

1.转化为dp问题。

例1:D - Just another Robbery

哈利波特要去抢银行,第i个银行有mi个金币,有pi的风险率被抓。问总风险率不超过P的情况下最多能抢多少金币。

想要计算风险是比较复杂的,因此我们考虑反面,计算安全率(安全率就是所抢银行的安全率之积,一个银行的安全率=1-pi)。

这就是一个背包问题。计f[i] 为抢到金币i所需的最大安全率

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define FASTIO() cin.sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;const double eps = 1e-9;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y)return y<x?x=y,1:0;
template<typename T>inline bool chkmax(T &x,const T &y)return x<y?x=y,1:0;
template <typename T> void inline read(T &x) 
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9')  if (s == '-') f = -1; s = getchar(); 
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;

int n,m,d;
int a[N];double p[N];
double P;
double f[N];
signed main()

	int cas;read(cas);
	int cnt = 0;
	while(cas--)
	
		printf("Case %d: ",++cnt);
		cin>>P;read(n); P = 1-P; 
		memset(f,0,sizeof f);
		for(int i=1;i<=n;i++)
		
			scanf("%d%lf",&a[i],&p[i]); 
			p[i] =  1-p[i];
		
		f[0] = 1;
		for(int i=1;i<=n;i++)
		
			for(int j=10000;j>=a[i];j--)
				f[j] = max(f[j],f[j-a[i]]*p[i]);
		
		for(int i=10000;i>=0;i--)
			if(f[i]>=P)
			
				cout<<i<<'\\n';
				break;
			
	    
    return 0;


ll qmi(ll a,ll b) ll res=1;a%=mod;  for(;b;b>>=1)if(b&1)res=res*a%mod;a=a*a%mod;return res;

例2:Dice (III)
题意,给定一个n面的骰子,不停投掷,求所有面都出现时投掷次数的期望。

假定f[i]代表出现i个面的期望。

如图,当出现i-1个面时,下一次操作有(i-1)/n的概率不会出现新的面,有(n-i+1)/n的概率会出现新面,因此出现新面的期望是概率的倒数,即为n/(n-i+1)
所以f[i] = f[i-1]+n/(n-i+1)

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define FASTIO() cin.sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;const double eps = 1e-9;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y)return y<x?x=y,1:0;
template<typename T>inline bool chkmax(T &x,const T &y)return x<y?x=y,1:0;
template <typename T> void inline read(T &x) 
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9')  if (s == '-') f = -1; s = getchar(); 
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;

int n,m,d;
int a[N];
double dp[N];
signed main()

	int cas;read(cas);
	int cnt = 0;
	while(cas--)
	
		dp[1] = 1;
		read(n);
		for(int i=2;i<=n;i++)
			dp[i] = dp[i-1]+1.0*n/(n-i+1);
		printf("Case %d: %.10lf\\n",++cnt,dp[n]); 
	    
    return 0;


ll qmi(ll a,ll b) ll res=1;a%=mod;  for(;b;b>>=1)if(b&1)res=res*a%mod;a=a*a%mod;return res;

例3:Where to Run
题意:

给你n(n<15)个点,m条无向边及其权值,你是一个刚偷完东西的小偷,身后有警察追你,因此你需要从1号点开始进行逃亡,在每个点你都有≥1个选择:

1、停留在原地5分钟

2、假设你在u号点,与u节点直接相连的点有v1,v2,…,vx号点,如果其中的某些节点到达它后可以通过这个节点遍历所有的点,那么你就可以选择这个点。选择每个合法点的概率是相等的,求你无路可走的时间期望
思路:

1、对于每个点u(编号0~n-1), 先找出所有可选择的点,假设有k个可选点

2、dp[zt][u]表示经过的点的状态为zt,目前在u点时走完所有点的时间期望(v为u的可选点)



化简可得
3、至于能否走完所有的点,做一下记忆化搜索就可以了

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define FASTIO() cin.sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 20 ,M = 1000010,mod = 998244353;const double eps = 1e-9;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y)return y<x?x=y,1:0;
template<typename T>inline bool chkmax(T &x,const T &y)return x<y?x=y,1:0;
template <typename T> void inline read(T &x) 
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9')  if (s == '-') f = -1; s = getchar(); 
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;

int n,m,d;
int a[N][N];
double f[1<<N][N];
bool ok[1<<N][N];
bool vis[1<<N][N];
int mm;
bool dfs(int st,int k)

	if(st==mm)
	
		f[st][k] = 0;
		return true;
	
	if(vis[st][k]) return ok[st][k];
	vis[st][k] = true;
	f[st][k] = 0;
	int cnt = 0;
	for(int i=0;i<n;i++)
	
		if(a[i][k]&&!(st>>i&1))
		
			if(dfs(st|(1<<i),i))
			
				++cnt;
				f[st][k]+=f[st|(1<<i)][i]+a[i][k];
				ok[st][k] = 1;
			 
		
	
	if(!ok[st][k]) return false;
	f[st][k] = (f[st][k]+5.0)/cnt;
	return true;
	
 
signed main()

	int cas;read(cas);
	int T = 0;
	while(cas--)
	
		read(n),read(m);
		memset(a,0,sizeof a);
		memset(ok,0,sizeof ok);
		memset(vis,0,sizeof vis);  
		mm = (1<<n)-1;
		for(以上是关于概率期望问题总结的主要内容,如果未能解决你的问题,请参考以下文章

LightOJ 1248 - Dice (III) 给一个质地均匀的n的骰子, 求投掷出所有点数至少一次的期望次数。(概率)

LightOJ 1248 - Dice (III) 给一个质地均匀的n的骰子, 求投掷出所有点数至少一次的期望次数。(概率)

LightOJ 1030 概率DP求期望

LightOJ1030(数学概率与期望)

HDU 4405:Aeroplane chess 概率DP求期望

ZOJ 3329:One Person Game 概率DP求期望(有环)