算法编程题积累(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 }