Check the difficulty of problems
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 6685 | Accepted: 2907 |
Description
Organizing a programming contest is not an easy job. To avoid making the problems too difficult, the organizer usually expect the contest result satisfy the following two terms:
1. All of the teams solve at least one problem.
2. The champion (One of those teams that solve the most problems) solves at least a certain number of problems.
Now the organizer has studied out the contest problems, and through the result of preliminary contest, the organizer can estimate the probability that a certain team can successfully solve a certain problem.
Given the number of contest problems M, the number of teams T, and the number of problems N that the organizer expect the champion solve at least. We also assume that team i solves problem j with the probability Pij (1 <= i <= T, 1<= j <= M). Well, can you calculate the probability that all of the teams solve at least one problem, and at the same time the champion team solves at least N problems?
1. All of the teams solve at least one problem.
2. The champion (One of those teams that solve the most problems) solves at least a certain number of problems.
Now the organizer has studied out the contest problems, and through the result of preliminary contest, the organizer can estimate the probability that a certain team can successfully solve a certain problem.
Given the number of contest problems M, the number of teams T, and the number of problems N that the organizer expect the champion solve at least. We also assume that team i solves problem j with the probability Pij (1 <= i <= T, 1<= j <= M). Well, can you calculate the probability that all of the teams solve at least one problem, and at the same time the champion team solves at least N problems?
Input
The input consists of several test cases. The first line of each test case contains three integers M (0 < M <= 30), T (1 < T <= 1000) and N (0 < N <= M). Each of the following T lines contains M floating-point numbers in the range of [0,1]. In these T lines, the j-th number in the i-th line is just Pij. A test case of M = T = N = 0 indicates the end of input, and should not be processed.
Output
For each test case, please output the answer in a separate line. The result should be rounded to three digits after the decimal point.
Sample Input
2 2 2 0.9 0.9 1 0.9 0 0 0
Sample Output
0.972一个概率dp的题插在了哈希里.......
这道题的意思就是说现在有T只队伍,要测试的题目M然后是对冠军队伍的期望最少要解出的题目。然后就是求每只队伍至少求出一题,冠军队伍至少求出N题事件发生的概率。
不难想到,我们可以计算出,每只队伍做出1-m(用P1表示)个题的概率,然后相乘,这样就能确保结果是每支队伍都能解出1-m个题,然后还有个约束条件就是冠军队至少要解出N题,也就是说我们应当去除每支队伍都求解出1-(n-1)(用P2表示)道题的情况,这样就可以确保至少有一只队伍是求解出n道题以上的,并且其余的队伍也是至少求解出1题。
然后问题就是怎么求解出P1和P2。
我们可以先求解出每支队伍的p1和p2,然后直接相乘就可以。
然后怎么求解p1和p2。我们分别用s1,s2代替。
借用一下别人的图片,可以看的更明白一些,然后我们可以去掉第一维。
递推式就是dp[j][k]=dp[j-1][k-1]*p[i][j]+dp[j-1][k]*(1-p[i][j]);
最后计算出,前M道题分别解出1、2、3、.....M道题的概率。相加之后就得到了s1,然后P1累乘
对于P2也是一样,到N-1,得到s2,P2累乘,最后相减即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <queue>
using namespace std;
const int MAXN=1000+5;
const int inf=0x3f3f3f;
int m,t,n;
double dp[35][35];
double p1,p2;
double p[MAXN][35];
double s1,s2;
int main()
{
while(~scanf("%d%d%d",&m,&t,&n))
{
if(!m&&!t&&!n)break;
int i,j,k;
for(i=1; i<=t; ++i)
for(j=1; j<=m; ++j)scanf("%lf",&p[i][j]);
memset(dp,0,sizeof(dp));//初始化dp数组
p1=1.0,p2=1.0;//p1用来记录每个队伍做1-m个题的概率,p2用来记录每个队伍做1~(n-1)个题目的概率
for(i=1; i<=t; ++i)
{
dp[0][0]=1.0;//前0道题做出0个题的概率自然是0
for(j=1;j<=m;++j)dp[j][0]=dp[j-1][0]*(1-p[i][j]);//前j个题做出0道题的概率
for(j=1;j<=m;++j)//计算每个队伍的dp值
{
for(k=1;k<=j;++k)
{
dp[j][k]=dp[j-1][k-1]*p[i][j]+dp[j-1][k]*(1-p[i][j]);
}
}
s1=0.0,s2=0.0;
for(j=1;j<=m;++j)s1+=dp[m][j];//记录这只队伍做1-m个题的概率
for(j=1;j<n;++j)s2+=dp[m][j];//和1-(n-1)个题的概率;
p1*=s1;
p2*=s2;
}
printf("%.3f\n",p1-p2);
}
return 0;
}