题意:
两列队伍,左边有
len1
个人,右边有
len2
个人,问事件左边没人但右边有人的概率。
两边收银员各有一个经验值参数
p
,
题解:
首先发现
F(p,k)
十分眼熟,满足几何分布,所以每秒成功收银的概率是
1/p
,设左边成功收银概率
a=1/p1
,右边为
b=1/p2
。
设左边没人但右边有人为事件
A
,则答案是求
然后就是DP,
DP[i][j]
表示左边有
i
人右边有
然后转移有四个方向:
- 左边成功但右边失败,概率是
a∗(1−b) - 左边成功且右边成功,概率是 a∗b
- 左边失败但右边成功,概率是 (1−a)∗b
- 左边失败且右边失败,概率是 (1−a)(1−b)
整理出转移方程。
DP[i][j]=DP[i−1][j]∗a∗(1−b)+DP[i−1][j−1]∗a∗b+DP[i][j−1]∗(1−a)∗b+DP[i][j]∗(1−a)∗(1−b)解出 DP[i][j]=(DP[i−1][j]∗a∗(1−b)+DP[i−1][j−1]∗a∗b+DP[i][j−1]∗(1−a)∗b)/(1−(1−a)∗(1−b)) 。
初始条件为 DP[0][0]=0,DP[0][i]=1(i>=1) 。
// BEGIN CUT HERE // END CUT HERE #line 5 "Queueing.cpp" #include<vector> #include<algorithm> #include<string.h> using namespace std; double dp[1005][1005]; class Queueing { private: void init(){ memset(dp, 0, sizeof(dp)); } public: double probFirst(int len1, int len2, int p1, int p2) { init(); for(int i = 1; i <= len2; ++i) dp[0][i] = 1; double a = 1.0/p1, b = 1.0/p2; for(int i = 1; i <= len1; ++i){ for(int j = 1; j <= len2; ++j){ dp[i][j] = dp[i-1][j]*a*(1-b)+dp[i][j-1]*(1-a)*b+dp[i-1][j-1]*a*b; dp[i][j] /= (1-(1-a)*(1-b)); } } return dp[len1][len2]; } };