[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 }