Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 4951 | Accepted: 2167 |
Description
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
Output
Sample Input
2 2 2 0.9 0.9 1 0.9 0 0 0
Sample Output
0.972
Source
题意:
ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率
问 每队至少解出一题且冠军队至少解出N道题的概率。
思路:
这道题分两部,首先考虑所有队都至少出一题的概率,再求所有队出题数都在1到n-1范围的概率,两者相减就是答案。
第一部分首先考虑每队至少出一题的概率,这个好说,用1减去该队一题不出的情况就是该队至少一题的情况,
最后乘到一起就是所有队都至少出一题的情况。
第二部分,考虑所有出题队出题数都为1~n-1的概率,这一部分要使用概率dp
设dp[i][j][k]为第i个队伍前j道题做出k道的概率,则状态方程显而易见:
dp[i][j][k]=p*dp[i][j-1][k-1]+(1-p)*dp[i][j-1][k]; p为做出第j道题的概率
最后一求和就是第二部分的概率,用第一部分的减去第二部分的就是答案了。
其中dp可以用滚动数组优化,能大大节约空间,反正过了,也懒得写了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N=1005;
const double eps=1e-5;
int n,m,t;
double a[N][33],ansp;
double dp[N][33][33];
void solve(){
double s=1;
for(int i=1;i<=t;i++){
double p=1;
for(int j=1;j<=m;j++){
scanf("%lf",&a[i][j]);
p*=1-a[i][j];
}
s*=1-p;//s为所有人都至少出一题的概率
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=t;i++){
dp[i][0][0]=1;
for(int j=1;j<=m;j++){
for(int k=0;k<=j;k++){
if(k>0)dp[i][j][k]=dp[i][j-1][k-1]*a[i][j];
dp[i][j][k]+=dp[i][j-1][k]*(1-a[i][j]);
}
}
}
double ans=1;
for(int i=1;i<=t;i++){
double sum=0;
for(int j=1;j<n;j++){
sum+=dp[i][m][j];
}
ans*=sum;
}
ans=s-ans;
printf("%.3f\n",ans);
}
int main()
{
while(scanf("%d%d%d",&m,&t,&n),m||t||n){
solve();
}
return 0;
}