题意:
给出n个技能,每个技能按输入顺序有p[i]的概率释放并造成d[i]的伤害。每轮游戏只能发动一个技能,问r轮游戏一共能造成的伤害期望。
题解:
神dp?!%%%
因为单独考虑每一轮很难设计出无后效性的状态(反正我是没想出来~~~于是看题解),将每一轮合(ho)在一起考虑。
于是最神的一招来了:设f[i][j]表示第i个技能有j次机会的概率。
先列出转移方程再解释:
前半截表示第i-1个技能未被释放,后半截表示释放了(释放的概率=1 - 一次都没轮上的概率)
P.S.多组数据注意每次清空f数组。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=224,MAXR=136;
double f[MAXN][MAXR],d[MAXN],p[MAXN];
int n,r;
inline double fpow(double a,int b) {
double ret=1.0;
while (b) {
if (b&1) ret=ret*a;
a*=a,b>>=1;
}
return ret;
}
int main() {
// freopen("bzoj 4008.in","r",stdin);
int kase;
scanf("%d",&kase);
while (kase--) {
memset(f,0,sizeof(f));
scanf("%d%d",&n,&r);
for (int i=1;i<=n;++i) scanf("%lf%lf",&p[i],&d[i]);
f[0][r]=1.0;
double ans=0.0;
for (int i=1;i<=n;++i)
for (int j=r;j;--j) {
f[i][j]=f[i-1][j]*fpow(1-p[i-1],j)+f[i-1][j+1]*(1-fpow(1-p[i-1],j+1));
ans+=f[i][j]*(1-fpow(1-p[i],j))*d[i];
}
printf("%.10lf\n",ans);
}
return 0;
}