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分鍾的概率是p i,j。
小C每次會選擇某一道沒做完的題,然后把它解決(不能中途放棄),之后再決策下一道要做的題是哪道。
求小C在最優策略下,期望能做出幾道題。
對於第i道題,小C解決它需要恰好j分鍾的概率是p i,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\n",dp[(1<<n)-1][m]); 46 return 0; 47 }