题意:两个账号,初始值是0,每次分数低的账号比赛,赢了加50分,输了扣100分,胜率为p,至其中一个账号=1000分为止,求比赛场次的期望值。
首先,状态(20,0),(20,1),(20,2)...(20,20) 的期望是0;
状态(i,j)的期望=( i , j + 1 ) + ( i , j - 2 ) * ( i - p ) + 1 ;
最后,高斯消元求解;
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cmath>
using namespace std;
const double eps=1e-9;
int mark[30][30],cnt;
double a[300][300];
double p;
void pre()//标号
{
memset(mark,-1,sizeof(mark));
cnt=0;
for (int i=0;i<20;i++)
for (int j=0;j<=i;j++)
mark[i][j]=cnt++;
}
double solve() //高斯消元
{
for (int i=0;i<cnt;i++)
{
int k=i;
for (;k<cnt;k++)
if (fabs(a[k][i])>eps) break;
for (int j=0;j<=cnt;j++)
swap(a[i][j],a[k][j]);
for (int j=0;j<cnt;j++)
{
if (i==j) continue;
if (fabs(a[j][i])>eps)
{
double x =a[j][i]/a[i][i];
for (int k=i;k<=210;k++)
{
a[j][k]-=a[i][k]*x;
}
}
}
}
return a[0][210]/a[0][0];
}
void doit()//列方程
{
memset(a,0,sizeof(a));
for (int i=0;i<20;i++)
for (int j=0;j<=i;j++)
{
int u=mark[i][j];
int v1=mark[max(i,j+1)][min(i,j+1)];
int v2=mark[max(i,max(j-2,0))][min(i,max(j-2,0))];
a[u][u]=1;
a[u][cnt]=1;
if (v1>=0&&v1<cnt)
a[u][v1]-=p;
if (v2>=0&&v2<cnt)
a[u][v2]-=(1-p);
}
}
int main()
{
pre();
while (~scanf("%lf",&p)){
doit();
double ans=solve();
printf("%.6lf\n",ans);
}
return 0;
}