1,普通的概率期望题,根据概率和期望的定义就好‘
1)注意加法原则和乘法原则,从小问题到大问题逐步地算概率
2)单点(或单块)的算期望再乘上相应概率
3)期望为概率的倒数
4)暴力模拟(记忆化搜索是一种好方法)
2,dp下的概率问题,和普通dp一样,注意概率为浮点数,尽量避开将其作为状态的一维。
3,逆推期望dp
一般用于求期望多少步达到某个目标。
假设终点为s,设dp[x]为从x点到达s点期望需要的步数,y和z同理。同时假设x点往前走一步,有1/2的几率到达y点,有1/2的几率到达z点。
那么:dp[x]=1+(dp[y]+dp[z])/2
dp[y]和dp[z]均为dp[x]的后继状态,所以为逆推。
4,顺推期望dp
看一道题:
链接:https://www.nowcoder.com/acm/contest/57/C
来源:牛客网
题目描述
小C现在要参加一场wannafly挑战赛,一场挑战赛一共有n道题,一共有m分钟。
对于第i道题,小C解决它需要恰好j分钟的概率是pi,j。
小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道。
求小C在最优策略下,期望能做出几道题。
对于第i道题,小C解决它需要恰好j分钟的概率是pi,j。
小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道。
求小C在最优策略下,期望能做出几道题。
输入描述:
第一行两个正整数n,mi,j
接下来一共n行,每行有m个小数,第i行的第j个小数表示p
(这里假设不存在0分钟A题的dalao)。
输出描述:
输出一个小数,表示期望能做出几道题,保留小数点后五位。
示例1:
输入
2 5 0.2 0.2 0.2 0.2 0.2 0 0.25 0.25 0.25 0.25
输出
1.30000
备注:
1≤ n≤ 6,1≤ m≤ 180
每道题的概率和为1(每道题只要时间够一定能做出来)
输入最多四位小数
这种显然的是正向递推,而在这里面的决策问题就是先做哪道题,后做哪道题,且花费了多少的时间。
数据量较小,直接状压dp。
与普通dp不一样的只是需要对子状态乘上一个概率。
1 #include <set> 2 #include <stack> 3 #include <queue> 4 #include <cmath> 5 #include <cstdio> 6 #include <string> 7 #include <cstring> 8 #include <iostream> 9 #include <algorithm> 10 using namespace std; 11 12 typedef long long ll; 13 double p[10][200],dp[(1<<6)+5][200]; 14 int main() 15 { 16 int n,m; 17 cin>>n>>m; 18 for(int i=1;i<=n;i++) 19 for(int j=1;j<=m;j++) 20 { 21 cin>>p[i][j]; 22 } 23 p[0][0]=0; 24 for(int i=1;i<=(1<<n)-1;i++) 25 { 26 for(int j=0;j<n;j++) 27 { 28 if((1<<j)&i) 29 { 30 int x=(1<<j)^i; 31 for(int k=1;k<=m;k++) 32 { double temp=0; 33 for(int y=0;y<k;y++) 34 { 35 temp+=(dp[x][y]+1)*p[j+1][k-y]; 36 } 37 dp[i][k]=max(dp[i][k],temp); 38 } 39 } 40 } 41 42 } 43 44 45 printf("%.5f ",dp[(1<<n)-1][m]); 46 return 0; 47 }