hdu 4870 Rating (概率dp)

题意:

给出一个人升级的流程,对于每次操作如果rank在1-200那么rating会涨min(x+50,1000),否则ranting会涨(x-100,0)相当于减rating。rank在1-200的范围的概率是p。

求rating达到1000操作数的期望。

题解在注释里。其实可以离散化,将x+50,1000,x-100,0离散化,就是x+1,20,x-2,0;

/**
对于单个账号的期望E[i]表示打到i分段的期望
令q=1-p;
E[i]=E[i+1]*p+E[i-2]*q;
显然这个没办法用递推,因为E[i+1]没计算出来。
这个暂且不提。
我们分析下两个账号的情况
在递推是肯定有这样:(0,0)->(0,1) (0,0)->(1,0) (1,0)->(2,0)....等
对于其中的(0,0)->(1,0)结果是E[1]-E[0],其他同理。
那么总的期望可以是这些差的和?猜测!将所有罗列出来,发现和的答案会累赘
就是说因为最后一步时(19,19)->(20,19)或者(19,19)->(19,20)这两者其中一个发
生就可以了,那么用之前的和减去E[20]-E[19];
那么我们令dp[i]=E[i+1]-E[i];
于是dp[i]=(dp[i-1]-dp[i-3]*q)/p;
结果为sum-dp[19];
*/
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
typedef unsigned long long ll;
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const int maxn=22;
double dp[maxn];

double DP(double p){

    memset(dp,0,sizeof dp);
    double sum=0;
    dp[0]=1/p;dp[1]=dp[0]/p;dp[2]=dp[1]/p;
    sum=dp[0]+dp[1]+dp[2];
    for(int i=3;i<20;i++){
        dp[i]=(dp[i-1]-dp[i-3]*(1.0-p))/p;
        sum+=dp[i];
    }
    return sum*2-dp[19];
}

int main(){

    double p;
    while(scanf("%lf",&p)!=EOF){
        printf("%.6lf\n",DP(p));
    }
	return 0;
}






你可能感兴趣的:(hdu 4870 Rating (概率dp))