版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Slow_Wakler/article/details/69659476
题目描述:
时间限制:C/C++语言 1000MS;其他语言 3000MS
内存限制:C/C++语言 65536KB;其他语言 589824KB
小明同学要参加一场考试,考试一共有n道题目,小明必须做对至少60%的题目才能通过考试。考试结束后,小明估算出每题做对的概率,p1,p2,…,pn。你能帮他算出他通过考试的概率吗?
输入
输入第一行一个数n(1<=n<=100),表示题目的个数。第二行n个整数,p1,p2,…,pn。表示小明有pi%的概率做对第i题。(0<=pi<=100)
输出
小明通过考试的概率,最后结果四舍五入,保留小数点后五位。
样例输入
4
50 50 50 50
样例输出
0.31250
Hint
第一个样例中,每道题做对的概率都是0.5,想要通过考试至少要做对三题。所以最后的答案就是0.31250。
解题思路
(1)令dp[i][j]
表示前面i题(包括i题)答对了j题
(2)令arr[i]
表示第i题答对的概率
(3)可得动态方程:dp[i][j] = dp[i-1][j]*(1.0-arr[i]) + dp[i-1][j-1]*arr[i];
(4)初始化:dp[0][0] = 1.0, dp[0][i] = 0(1<=i<=n), dp[1][0] = 1.0-arr[1], dp[i][0] = dp[i-1][0]*(1.0-arr[i]), dp[i][j] = 0(i<j)
代码
import java.util.*;
public class Main {
static double[][] dp = new double[105][105];
public static void main(String []args){
Scanner sc = new Scanner(System.in);
double[] arr = new double[110];
while(sc.hasNext()) {
int n = sc.nextInt();
for(int i = 1; i <= n; i++) {
int a = sc.nextInt();
arr[i] = 0.01*a;
}
int goal = (int)Math.ceil(0.6*n);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n; j++)dp[i][j] = 0;
dp[0][0] = 1.0;
for(int i = 1; i <= n; i++) {
dp[0][i] = 0;
}
dp[1][0] = 1.0-arr[1];
for(int i = 2; i <= n; i++)dp[i][0] = dp[i-1][0]*(1.0-arr[i]);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
if(i-1>=j)dp[i][j] = dp[i-1][j]*(1.0-arr[i]) + dp[i-1][j-1]*(arr[i]);
else dp[i][j] = dp[i-1][j-1]*(arr[i]);
}
}
double ans = 0.0;
for(int i = goal; i <= n; i++) {
ans += dp[n][i];
}
System.out.println(String.format("%.5f", ans));
}
}
}