题意:
进行一局游戏,你有 p 的概率获胜。有一个概率 q 初始为 2% ,如果你获胜,你将有 q 的概率获得奖励;如果你没得到奖励, q 会变化, ;如果你输了, q 也会变化, 。
问获得奖励的期望局数为多少。
分析:
很明显的期望 dp 。对于普通的期望 dp ,一般是把结局的概率作为1,从开始进行记忆化递归。但是对于本题。开始时没有得到奖励,就是0,得到奖励就是1,只有 0->1 ,显然不行。
既然是dp,那就要有多条转移路径的状态,将状态作为dp数组的下标。发现本题中 q 是有多条转化的路径的,我们不妨将 q 作为状态。但是作为数组下标一定要是整数,那就,即100%对应 ,25.5%对应 。
表示当 时,得到奖励的期望。
期望=概率*局数
//这一局没赢,以后获得了奖励;
//这一局赢了,且获得了奖励;
//这一局赢了,但没获得奖励,以后获得了奖励,别忘了*(1-q),代表没获得奖励
注意转移的时候要加1,即当前没赢的这一局。本局直接获得奖励的话,所需局数是1;否则就是下一个状态的局数+1.
我们把上下两项的“1”提出来,与p*q组合
综上所述,
那么开始时状态就是 , 结束时状态就是 。
即使,但是可能这局输了,根本就没机会的奖励
因为直接写的等于1,检查了好久
证明其实就是很简单,如果这一把输了,下一把的q仍为100%。
设
E=(1-p)*E+1+p*(1-1)*E
化简可得
至此,答案显然易见。
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int N=1e3+5;
const double eps=1e-6;
typedef long double ld;
ld dp[N];
ld p;
void dfs(int rate)
{
ld q=(double)rate/1000.0;
int nxt1=min(rate+15,1000),nxt2=min(rate+20,1000);
if(nxt1<1000&&fabs(dp[nxt1])<eps) dfs(nxt1);
if(nxt2<1000&&fabs(dp[nxt2])<eps) dfs(nxt2);
dp[rate]=(1-p)*dp[nxt1]+1+p*(1-q)*dp[nxt2];
}
int main()
{
int t;
cin>>t;
for(int it=1;it<=t;it++)
{
cin>>p;
memset(dp,0,sizeof(dp));
p/=100;
dp[1000]=1.00/p;
dfs(20);
cout<<"Case "<<it<<": "<<fixed<<setprecision(10)<<dp[20]<<endl;
}
}