算法编程题积累(2)——京东笔试“求概率”问题

首先关于这道题,暴力求解肯定是不可取的。核心思路是利用动态规划(DP)建立概率表来解决。

我们注意到问题的关键是如何求得前 i 道题有 j 道题答对的概率。用f[i]表示第 i 道题答对的概率。

用dp[i][j]来表示前 i 道题有 j 道题答对的概率,因而根据第 i 道题是否答对可以有递推公式:dp[i][j] = dp[i-1][j] *(1- f[i]) + dp[i-1][j-1] * f[i];

有了这个核心思路,接下来要注意边界问题:当i=0时或j=0时的考虑。易知:dp[0][0] = 1.0    dp[i][0] = dp[i-1][0] * (1-f[i]) 

除此之外,要注意向上取整的小技巧:例如对a*0.6向上取整可有:int low = (a*3+4)/5;

AC Code如下:

 1 #include <bits/stdc++.h>
 2 #define maxn 110
 3 using namespace std;
 4 
 5 int n, a[maxn];
 6 double dp[maxn][maxn];
 7 
 8 int main()
 9 {
10     scanf("%d",&n);
11     for(int i = 1; i <= n; i++)
12         scanf("%d",&a[i]);
13     
14     dp[0][0]=1;
15     //dp[i][j]表示前i道题做对j道题的概率
16     for(int i = 1; i <= n; i++){
17         dp[i][0]=dp[i-1][0]*(100.0-a[i])/100;
18         for(int j = 1;j <= i; j++)
19             dp[i][j] = dp[i-1][j]*(100-a[i])/100.0 + dp[i-1][j-1]*a[i]/100.0;
20     }
21     
22     int low = (3*n+4)/5;//向上取整
23     double ans = 0.0;
24     for(int i = low; i <= n; i++)
25         ans += dp[n][i];
26     printf("%.5f\n",ans);
27     return 0;
28 }

 

posted @ 2017-04-07 23:17  甘乐  阅读(653)  评论(0编辑  收藏  举报