转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1304863551
大致题意:
ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率
问 每队至少解出一题且冠军队至少解出N道题的概率。
解题思路:
真费解为什么这题被划分到了Hash。。。
明明是 概率+DP ,概率不好真的拿不下这题T .T,建议数学不好的同学直接放弃算了。。。这题难点不在编程,在于问题的转化和理解= =只要能用笔算出答案,离AC也就不远了。。。
要求:每队至少解出一题 且 冠军队至少解出N道题的概率
由于冠军队可以不止一队,即允许存在并列冠军
则原来的所求的概率可以转化为:
每队均至少做一题的概率P1 减去 每队做题数均在1到N-1之间的概率P2
1 //Memory Time
2 //8272K 110MS
3
4 #include<iostream>
5 #include<iomanip>
6 using namespace std;
7
8 int M,T,N; //M:题数 T:队数 N:冠军队至少做题数
9 double dp[1001][31][31]; //状态方程: dp[i][j][k]为第i队PASS前j题中的k题的概率
10
11 double p[1001][31]; //p[i][j]为第i队通过第j题的概率
12 double s[1001][31]; //s[i][j]为第i队在M题中至少PASS j题的概率
13
14 void ProTable(void) //概率打表
15 {
16 memset(dp,0.0,sizeof(dp));
17 memset(s,0.0,sizeof(s));
18
19 int i,j,k;
20 for(i=1;i<=T;i++) //逐队枚举
21 {
22 /*Initial*/
23
24 dp[i][0][0]=1.0;
25
26 for(j=1;j<=M;j++)
27 dp[i][j][0]=dp[i][j-1][0]*(1-p[i][j]);
28
29 /*Dp*/
30
31 for(j=1;j<=M;j++)
32 for(k=1;k<=j;k++)
33 dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j]);
34
35 s[i][0]=dp[i][M][0];
36 for(k=1;k<=M;k++)
37 s[i][k]=s[i][k-1]+dp[i][M][k];
38 }
39 return;
40 }
41
42 int main(int i,int j)
43 {
44 while(cin>>M>>T>>N)
45 {
46 if(!M && !T && !N)
47 break;
48
49 /*Input*/
50
51 for(i=1;i<=T;i++)
52 for(j=1;j<=M;j++)
53 cin>>p[i][j];
54
55 /*Compute the Probability*/
56
57 ProTable();
58
59 double p1=1.0;
60 for(i=1;i<=T;i++)
61 p1*=(s[i][M]-s[i][0]); //所有队至少做1题的概率
62
63 double p2=1.0;
64 for(i=1;i<=T;i++)
65 p2*=(s[i][N-1]-s[i][0]); //所有队做的题数均在1~N-1之间的概率
66
67 /*Output*/
68
69 cout<<fixed<<setprecision(3)<<p1-p2<<endl;
70 //每队至少解出一题 且 至少有一队(冠军队)能至少解出N道题的概率
71 }
72 return 0;
73 }