XDOJ 1020 ACMer去刷题吧(基础dp)

题目描述

刷题是每个ACMer必由之路,已知某oj上有n个题目,第i个题目小X能做对的概率为Pi(0<=Pi<=1,1<=i<=n) 求小X至少做对k道题的概率

输入

第一行输入一个正整数t,(t<=20),表示有t组测试样例。 第二行输入正整数n,k,(1<=n,k<=1000) 第三行输入n个小数,分别为Pi(1<=i<=n,0<=Pi<=1),表示小X做对第i个题目的概率。

输出

输出小X至少做对k道题的概率,并换行(保留4位小数)

样例输入

2
1 1
0.5
3 2
0.3 0.2 0.1

样例输出

0.5000
0.0980

提示

题目大意:

  这题就是说,给你一个每道题做对的概率,然后,让你求出来至少做对k道题的概率是多少.

解题思路:

  其实不难,只要推出来dp[i][j]玩就好了,一开始推了一会,,少了个条件(Q神给窝补上去了)

  状态:dp[i][j]表示的是有i道题,作对j道题的概率。

  初始状态:dp[0][0] = 1,dp[0][1] = 0;

  状态转移方程:dp[i][j] = dp[i-1][j-1]*p[i]+dp[i-1][j]*(1-p[i]);

         dp[i][0] = (1-p[i])*dp[i-1][0]

  最后只要求出来sum+=dp[n][k]+dp[n][k+1]+dp[n][k+2]+...+dp[n][n];

代码:

 1 # include<cstdio>
 2 # include<iostream>
 3  
 4 using namespace std;
 5  
 6 # define MAX 1234
 7  
 8 double p[MAX];
 9 double dp[MAX][MAX];
10 int n,k;
11  
12 int main(void)
13 {
14     int t;scanf("%d",&t);
15     while ( t-- )
16     {
17         scanf("%d%d",&n,&k);
18         for ( int i = 1;i <= n;i++ )
19         {
20             scanf("%lf",&p[i]);
21         }
22         dp[0][0] = 1;
23         dp[0][1] = 0;
24         for ( int i = 1;i <= n;i++ )
25         {
26             dp[i][0] = (1-p[i])*dp[i-1][0];
27         }
28         for ( int i = 1;i <= n;i++ )
29         {
30             for ( int j = 1;j <= n;j++ )
31             {
32                 dp[i][j] = (1-p[i])*dp[i-1][j]+p[i]*dp[i-1][j-1];
33             }
34         }
35         double sum = 0;
36         for ( int i = k;i <= n;i++ )
37         {
38             sum+=dp[n][i];
39         }
40        printf("%.4lf\n",sum);
41  
42     }
43  
44  
45     return 0;
46 }

 

posted @ 2015-04-25 00:35  BYYB_0506  阅读(631)  评论(0编辑  收藏  举报