POJ 2151 Check the difficulty of problems
这道题是一道概率DP题,好难啊!!!
题目大体是这个意思:
ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率
问 每队至少解出一题且冠军队至少解出N道题的概率(冠军可以并列)。
看题解看懂的,表示大牛们真的好强。因为冠军不一定有多少,所以这题需要转化为:
求每队均至少做一题的概率P1 减去 每队做题数均在1到N-1之间的概率P2。
再次感谢大牛可以让我盗图,本事不够只能这样了,慢慢学吧。
下面是代码:
#include <stdio.h> #include <string.h> double p[1003][33],dp[1003][33][33],s[1003][33]; int main() { int m,t,n; while(scanf("%d%d%d",&m,&t,&n),m||t||n) { int i,j,k; double p1=1,p2=1,temp; for(i=1; i<=t; i++) { for(j=1; j<=m; j++) { scanf("%lf",&p[i][j]); } } memset(dp,0.0,sizeof(dp)); memset(s,0.0,sizeof(s)); for(i=1; i<=t; i++) //逐队枚举 { dp[i][0][0]=1.0; for(j=1; j<=m; j++) { dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]); //初始化每队前J题都答不上来的概率 } for(j=1; j<=m; j++) { for(k=1; k<=j; k++) { dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j]); /**第I队当解到第J题时解出K个题的概率是解前J-1个题时解出K-1个的概率乘以解出第 J题的概率加上解前J-1个题时解出K个的概率乘以第J个题没解出的概率*/ } } s[i][0]=dp[i][m][0];//最后第I队解0个题的概率是dp[i][m][0];及第I队做M题做出0道的概率。 for(k=1; k<=m; k++) { s[i][k]=s[i][k-1]+dp[i][m][k]; //第I队解出K道题的概率是第I队解出K-1道题的概率加上及第I队做M题做出K道的概率。 } } //p1为每队均至少做一题的概率,p2为每队做题数均在1到N-1之间的概率。 for(i=1; i<=t; i++) { p1*=(s[i][m]-s[i][0]); } for(i=1; i<=t; i++) { p2*=(s[i][n-1]-s[i][0]); } printf("%.3lf\n",p1-p2); } return 0; }