题目链接:Batting Practice - LightOJ 1408 - Virtual Judge (ppsucxtt.cn)
题意:一个人在练习棒球,击不中的概率为p。如果连续k1次击中,或者连续k2 次击不中,就停止练习。求练习的期望次数。
这道题是一道概率dp题,我们设f[i]为已经连续击中i次后距离停止联系所需的期望次数,g[i]为已经连续未击中i次后距离停止联系所需的期望次数,则可以进行动态转移,转移过程的推导在下图:
有了g[1]和f[1]显然就可以得到 ans=p*f[1]+(1-p)*g[1]+1 此处的p为击中的概率,1就是当前的操作次数。唯一需要注意的就是特判等于1或者0的情况。
下面是代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
int T;
cin>>T;
double p;
int k1,k2;
for(int o=1;o<=T;o++)
{
cin>>p>>k1>>k2;
p=1-p;
if(fabs(p)<1e-6)
{
printf("Case %d: %d\n",o,k2);
continue;
}
else if(fabs(p-1)<1e-6)
{
printf("Case %d: %d\n",o,k1);
continue;
}
double C=1-pow(p,k1-1.0);
double D=1-pow(1-p,k2-1.0);
double ans1=C*D/p/(1-C*D)+C/(1-p)/(1-C*D);
double ans2=D*ans1+D/p;
printf("Case %d: %.10lf\n",o,ans1*p+(1.0-p)*ans2+1);
}
return 0;
}