一种计算答案的方法,即每张牌的伤害×这张牌在整局游戏里被抽中的概率
因为对于每张牌,会影响到他的概率的只有他前面的牌,他后面的牌是否抽中对他没有影响
而一轮一轮过情况很复杂,不妨将r轮视为r个机会,将所有牌和所有机会一起考虑
f[i][j]
为前
i
张牌,用剩j 次机会的概率
可以得到一个方程:
f[i][j]=f[i−1][j]×(1−p[i])j+f[i−1][j+1]×(1−(1−p[i])j+1)
方程前面一项指第 i 张牌没有用掉这一次机会,后面那一项即第
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 300;
const int maxr = 300;
double p[maxn],pw[maxn][maxr];
double f[maxn][maxr];
int a[maxn];
double ans;
int n,r;
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&r);
for(int i=1;i<=n;i++)
{
scanf("%lf%d",&p[i],&a[i]);
p[i]=1-p[i];
}
for(int i=1;i<=n;i++)
{
pw[i][0]=1.0;
for(int j=1;j<=r;j++) pw[i][j]=pw[i][j-1]*p[i];
}
ans=0.0;
for(int i=0;i<maxn;i++)for(int j=0;j<maxr;j++)f[i][j]=0.0;
f[0][r]=1.0;
for(int i=1;i<=n;i++)
{
double s=0.0;
for(int j=r;j>=0;j--)
{
f[i][j]=f[i-1][j]*pw[i][j]+f[i-1][j+1]*(1-pw[i][j+1]);
s+=f[i-1][j+1]*(1-pw[i][j+1]);
}
ans=ans+s*double(a[i]);
}
printf("%.10lf\n",ans);
}
return 0;
}