ZOJ3582-Back to the Past-概率dp

一共左右两排共2N盏灯,计算每排都亮M盏以上的期望。每天每盏灯有P的概率点亮。

dp[i][j]记录左边i盏右边j盏时的期望,从dp[N][N]往前推。//没学概率论写的好懵逼。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 const int maxn = 50+5;
 9 int N,M;
10 double P,dp[maxn][maxn],Yes[maxn],No[maxn],C[maxn][maxn];
11 
12 void init()
13 {
14     for(int i=0;i<=maxn;i++)
15     {
16         C[i][0] = C[i][i] = 1.0;
17         for(int j=1;j<i;j++)
18             C[i][j] = C[i-1][j-1]+C[i-1][j];
19     }
20 }
21 
22 int main()
23 {
24     init();
25     while(scanf("%d%d%lf",&N,&M,&P))
26     {
27         if(N==0&&M==0) break;
28         //cout << P << endl;
29         memset(dp,0,sizeof dp);
30         Yes[0]=No[0]=1;
31         for(int i=1;i<=N;i++)
32         {
33             Yes[i] = Yes[i-1]*P;
34             No[i] = No[i-1]*(1.0-P);
35         }
36 
37         for(int i=N;i>=0;i--)
38         {
39             for(int j=N;j>=0;j--)
40             {
41                 if(i>=M&&j>=M) continue;
42                 double sum = 0;
43                 for(int x=0;x+i<=N;x++)
44                 {
45                     for(int y=0;y+j<=N;y++)
46                     {
47                         if(x==0&&y==0) continue;
48                         if(N-i>=x&&N-j>=y)
49                             sum += dp[x+i][y+j]*C[N-i][x]*Yes[x]*No[N-i-x]*C[N-j][y]*Yes[y]*No[N-j-y];
50                     }
51                 }
52                 dp[i][j] = (sum+1.0)/(1.0-No[N-i]*No[N-j]);
53             }
54         }
55 
56         printf("%.6f\n",dp[0][0]);
57     }
58 }

 

posted @ 2016-02-21 23:14  Helica  阅读(212)  评论(0编辑  收藏  举报