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;
}