# BZOJ4008：[HNOI2015]亚瑟王 （概率DP）

$g\left[i+1\right]\left[j\right]=g\left[i\right]\left[j\right]\ast \left(1-p\left[i+1\right]{\right)}^{r-j}$

$g\left[i+1\right]\left[j+1\right]=g\left[i\right]\left[j\right]\ast \left(1-\left(1-p\left[i+1\right]{\right)}^{r-j}\right)$

CODE：

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;

const int maxn=233;
typedef long double LD;

LD f[maxn][maxn];
LD g[maxn][maxn];
LD pk[maxn][maxn];

LD p[maxn];
int d[maxn];
int t,n,r;

int main()
{
freopen("4008.in","r",stdin);
freopen("4008.out","w",stdout);

scanf("%d",&t);
while (t--)
{
memset(f,0.0,sizeof(f));
memset(g,0.0,sizeof(g));
g[0][0]=1.0;

scanf("%d%d",&n,&r);
for (int i=1; i<=n; i++)
scanf("%Lf%d",&p[i],&d[i]),p[i]=1.0-p[i],pk[i][0]=1.0;
for (int i=1; i<=n; i++)
for (int j=1; j<=r; j++)
pk[i][j]=pk[i][j-1]*p[i];

for (int i=0; i<n; i++)
for (int j=0; j<=r; j++)
{
g[i+1][j]+=(g[i][j]*pk[i+1][r-j]);
f[i+1][j]+=(f[i][j]*pk[i+1][r-j]);
if (j==r) continue;

g[i+1][j+1]+=(g[i][j]*(1.0-pk[i+1][r-j]));
f[i+1][j+1]+=((f[i][j]+(LD)d[i+1]*g[i][j])*(1.0-pk[i+1][r-j]));
}

LD ans=0.0;
for (int i=0; i<=r; i++) ans+=f[n][i];
printf("%.10Lf\n",ans);
}

return 0;
}

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客