好了现在开始写那个走错门的概率DP
对于概率DP,我之前真的是一无所知,遇到这种题目就直接跪了
其实这道题还是挺适合入门的(很好的体现了各个公式的运用)
题意大概是有T只队伍和M道题目。给出每个队伍解决每道题目的概率,让你求所有队伍均至少做出1题且冠军队伍做出至少N题的概率。
我们设f[i][j][k]表示第i只队伍在前j题中做出k题的概率,则有以下转移:
f[i][j][k]=f[i][j-1][k-1]*p[i][j]+f[i][j-1][k]*(1-p[i][j]);
很好理解吧,第k题做出来和没做出来的概率相加
再设sum[i][j]表示第i只队伍在m道题中做出j题的概率,则:
sum[i][j]=sum[i][j-1]+f[i][m][k];
然后我们想一下,要求所有的队伍做出一题的概率p1就是:
p1*=sum[i][m]-sum[i][0];
但是还要满足最多的队伍做出n题,我们转化一下可以统计出所有队伍均做出1题且都不超过n题的概率p2:
p2*=sum[i][n-1]-sum[i][0];
要满足要求,所以ans就是p1-p2了
#include<cstdio>
using namespace std;
const int M=35,T=1005;
int n,m,t;
double f[T][M][M],p[T][M],sum[T][M],p1,p2;
int main()
{
register int i,j,k;
for (;;)
{
scanf("%d%d%d",&m,&t,&n);
if (!m&&!t&&!n) break;
for (i=1;i<=t;++i)
for (j=1;j<=m;++j)
scanf("%lf",&p[i][j]);
for (i=1;i<=t;++i)
f[i][0][0]=1;
for (i=1;i<=t;++i)
for (j=1;j<=m;++j)
f[i][j][0]=f[i][j-1][0]*(1-p[i][j]);
for (i=1;i<=t;++i)
{
for (j=1;j<=m;++j)
for (k=1;k<=j;++k)
f[i][j][k]=f[i][j-1][k-1]*p[i][j]+f[i][j-1][k]*(1-p[i][j]);
for (sum[i][0]=f[i][m][0],k=1;k<=m;++k)
sum[i][k]=sum[i][k-1]+f[i][m][k];
}
for (p1=1,p2=1,i=1;i<=t;++i)
{
p1*=(sum[i][m]-sum[i][0]);
p2*=(sum[i][n-1]-sum[i][0]);
}
printf("%.3lf
",p1-p2);
}
return 0;
}