[ZHOJ1956]vfk的地雷

题目大意:
  有$n$个开关,$r$句话。
  每个开关$i$有$p_i$的概率被触发,并造成$d_i$的代价。
  每个开关至多被触发一次,一句话至多触发一个开关。
  每个开关按照顺序被尝试触发。
  求期望代价。

思路:
  动态规划。
  用$f_{i,j}$表示前$i$个开关被触发$j$次的概率,
  用$g_{i,j}$表示前$i$个开关被触发$j$次所造成代价的期望。
  那么$f_{i,j}=f_{i-1,j}\times(1-p_i)^{r-j-1}+f_{i-1,j-1}\times(1-(1-p_i)^{r-j-1})$。
  其中$f_{i-1,j]}\times(1-p_i)^{r-j-1}$表示开关不被触发的概率,
  $f_{i-1,j-1}\times(1-(1-p_i)^{r-j-1})$表示开关被触发的概率。
  我们能得到$g_{i,j}=g_{i-1,j}\times(1-p_i)^{r-j-1}+(g_{i-1,j-1}+d_{i}\times f_{i-1,j-1})\times(1-(1-p_i)^{r-j-1})$
  最后统计$g_n$的和即可。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 const int N=221,R=133;
12 double p[N],d[N],f[N][R],g[N][R];
13 int main() {
14     for(register int T=getint();T;T--) {
15         int n=getint(),r=getint();
16         for(register int i=1;i<=n;i++) {
17             scanf("%lf%lf",&p[i],&d[i]);
18         }
19         memset(f,0,sizeof f);
20         memset(g,0,sizeof g);
21         f[0][0]=1;
22         for(register int i=0;i<n;i++) {
23             register double q=1;
24             for(register int j=r;~j;j--) {
25                 f[i+1][j]+=f[i][j]*q;
26                 g[i+1][j]+=g[i][j]*q;
27                 f[i+1][j+1]+=f[i][j]*(1-q);
28                 g[i+1][j+1]+=(g[i][j]+d[i+1]*f[i][j])*(1-q);
29                 q*=(1-p[i+1]);
30             }
31         }
32         double ans=0;
33         for(register int i=1;i<=r;i++) {
34             ans+=g[n][i];
35         }
36         printf("%.10f\n",ans);
37     }
38     return 0;
39 }

 

posted @ 2017-09-27 12:28  skylee03  阅读(128)  评论(0编辑  收藏  举报