首先我们以50分为一单位,于是赢一次得1分输一次扣2分,由于每次都用小号打,所以容易观察出最后达到20分时应该分别为20分和19分。我们设dp[i]为i到i+1分的期望步数。则dp[i]=p*1+(1-p)*(dp[i-2]+dp[i-1]+dp[i]+1),前者是赢的期望,后者由于输了2分,所以变成i+1分时需要从i-2->i-1->i->i+1,就是dp[i-2]+dp[i-1]+dp[i]+1了,f[i][j]表示大号为i分小号为j分的步数期望,Dp即可
代码https://github.com/mlz000/hdu/blob/master/4870(%E6%A6%82%E7%8E%87Dp).cpp
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=25; double dp[N],f[N][N]; int main(){ double p; while(~scanf("%lf",&p)){ dp[0]=1.0/p,dp[1]=1.0/p+(1.0-p)/p*dp[0]; for(int i=2;i<=19;++i) dp[i]=1.0/p+(1.0-p)/p*(dp[i-2]+dp[i-1]); f[1][0]=dp[0],f[1][1]=f[1][0]+dp[0]; for(int i=1;i<=19;++i){ f[i+1][i]=f[i][i]+dp[i]; f[i+1][i+1]=f[i+1][i]+dp[i]; } printf("%.10lf\n",f[20][19]); } return 0; }
原文地址:http://blog.csdn.net/mlzmlz95/article/details/38143861