DP Training I 简单概率DP
DP Training I 简单概率DP
题意
翻\(n\)次硬币,对于第\(i\)个硬币, 每次有\(p_i\)的概率正面。问\(n\)次后正面次数大于反面次数的概率
\[1 \leq n \leq 2999
\\
0< p_i < 1
\]
分析
考虑每次计算概率都要在前面的基础上乘
直接设计状态\(dp[i][j]\)表示到现在有\(i\)个正面\(j\)个反面的概率
\[dp[i][j] += dp[i - 1][j] \times p[i]\\
dp[i][j] += dp[i][j - 1] \times (1 - p[i])\\
dp[0][0] = 1
\]
代码
double p[3005];
double dp[3005][3005];
int main(){
int n = rd();
for(int i = 1;i <= n;i++)
scanf("%lf",&p[i]);
dp[0][0] = 1.0;
for(int i = 1;i <= n;i++){
for(int j = 0;j <= i;j++){
int x = j;
int y = i - j;
if(x) dp[x][y] += dp[x - 1][y] * p[i];
if(y) dp[x][y] += dp[x][y - 1] * (1 - p[i]);
}
}
double ans = 0;
for(int i = 0;n - i > i;i++){
ans += dp[n - i][i];
}
printf("%.10f",ans);
}