题目链接:http://poj.org/problem?id=2151
题意:t支队伍m个题,求在每支队伍至少完成一道题的情况下冠军队伍至少完成n个题的概率。
思路:
这道题一开始是放在哈希的题目列表里面..看完题后感觉完全和哈希没关系呃..
感觉又是#没有思路无法下手,有了思路就会觉得很简单系列#的一道题,好纠结...
用dp[i][j][k]表示第i支队伍在前j道题中完成k道题的概率
易得dp[i][j][k]=dp[i][j-1][k-1]*a[i][j]+dp[i][j-1][k]*(1-a[i][j]);
初始化:
dp[i][0][0]=1.0;(即第i支队伍在前0道题中完成0道题的概率始终为1)
dp[i][j][0]=dp[i][j-1][0]*(1-a[i][j]);
ans=所有队伍至少完成一道题的概率(即1-dp[i][m][0])-所有冠军队伍均完成至少n个题的概率(即t支队伍dp[i][m][1...n-1]的乘积);
(之所以用减号而不是乘号是因为前者的概率中包含后者)
最后还要注意:
冠军队伍可能不只一支
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; const int INF=0x3f3f3f3f; const int maxn=1005; int m,t,n; double dp[maxn][35][35]; double a[maxn][35]; void Read(){ for(int i=1;i<=t;i++) for(int j=1;j<=m;j++) scanf("%lf",&a[i][j]); } void init(){ memset(dp,0,sizeof(0)); for(int i=1;i<=t;i++) dp[i][0][0]=1.0; for(int i=1;i<=t;i++){ for(int j=1;j<=m;j++){ dp[i][j][0]=dp[i][j-1][0]*(1-a[i][j]); } } } void Dynamic_Programming(){ for(int i=1;i<=t;i++){ for(int j=1;j<=m;j++){ for(int k=1;k<=m;k++){ dp[i][j][k]=dp[i][j-1][k-1]*a[i][j]+dp[i][j-1][k]*(1-a[i][j]); } } } } int main(){ #ifndef ONLINE_JUDGE freopen("test.in","r",stdin); freopen("test.out","w",stdout); #endif while(~scanf("%d%d%d",&m,&t,&n)){ if(m==0&&t==0&&n==0) break; Read(); init(); Dynamic_Programming(); double ans=1.0; for(int i=1;i<=t;i++) ans*=1-dp[i][m][0]; double pro=1.0; for(int i=1;i<=t;i++){ double sumPro=0.0; for(int j=1;j<=n-1;j++){ sumPro+=dp[i][m][j]; } pro*=sumPro; } ans-=pro; printf("%.3f\n",ans); } return 0; }