hdu4870 一个人有两个账号,每次拿rating低的号打,p的概率加50,1-p的概率减100,求任意一个号到1000分的期望场数:期望dp+高斯消元
每50分为1分,减少状态。
首先dp[i][j]=p*(dp[i+1][j]或dp[j][i+1])+(1-p)*dp[i-2][j]+1 这是入门的期望公式了
利用id(i,j)=(i-i*i)/2+20*i+j来标序
形成环了,高斯消元解出方程,x[0]即为dp[0][0]的期望了==
1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 #define eps 1e-8 7 int cal(int i,int j) 8 { 9 return (i-i*i)/2+20*i+j; 10 } 11 double g[235][235],x[235]; 12 int row,col; 13 int guass() 14 { 15 int tr,tc,i,j,max_r; 16 for (tr=0,tc=0;tc<=col;tc++) 17 { 18 max_r=tr; 19 for (i=tr;i<=row;i++) 20 if (fabs(g[i][tc])>fabs(g[max_r][tc])) max_r=i; 21 if (fabs(g[max_r][tc])<eps) return 0; 22 if (max_r!=tr){ 23 for (j=tc;j<=col;j++) swap(g[max_r][j],g[tr][j]); 24 swap(x[max_r],x[tr]); 25 } 26 for (j=tc+1;j<=col;j++) g[tr][j]/=g[tr][tc]; 27 x[tr]/=g[tr][tc]; g[tr][tc]=1; 28 for (i=0;i<=row;i++) 29 if (i!=tr) 30 { 31 for (j=tc+1;j<=col;j++) g[i][j]-=g[i][tc]*g[tr][j]; 32 x[i]-=x[tr]*g[i][tc]; g[i][tc]=0; 33 } 34 tr++; 35 } 36 return 1; 37 } 38 int main() 39 { 40 int i,j,id,tmp_id,ti,tj; 41 double p; 42 while (~scanf("%lf",&p)) 43 { 44 memset(g,0,sizeof(g)); 45 memset(x,0,sizeof(x)); 46 for (i=0;i<=20;i++) 47 for (j=i;j<=20;j++) 48 { 49 id=cal(i,j); 50 g[id][id]+=1; 51 if (i==20||j==20) continue; 52 ti=min(i+1,j); tj=max(i+1,j); 53 tmp_id=cal(ti,tj); 54 g[id][tmp_id]-=p; 55 ti=max(0,i-2); tj=j; 56 tmp_id=cal(ti,tj); 57 g[id][tmp_id]-=1-p; 58 x[id]+=1; 59 } 60 row=col=230; 61 guass(); 62 printf("%.6lf\n",x[0]); 63 } 64 return 0; 65 }