定义 d p [ i ] [ j ] dp[i][j] dp[i][j]为当前主角位置在 j j j,首位的人已经连续赢了 i i i局比赛的概率
当 j > 4 j>4 j>4时
d p [ i ] [ j ] = d p [ i + 1 ] [ j − 3 ] ∗ 1 4 + d p [ 1 ] [ j − 3 ] ∗ 3 4 dp[i][j]=dp[i+1][j-3]*\frac{1}{4}+dp[1][j-3]*\frac{3}{4} dp[i][j]=dp[i+1][j−3]∗41+dp[1][j−3]∗43
当 j = = 1 j==1 j==1
d p [ i ] [ j ] = d p [ i + 1 ] [ j ] ∗ 1 4 + d p [ 1 ] [ n − 2 ] ∗ 3 4 dp[i][j]=dp[i+1][j]*\frac{1}{4}+dp[1][n-2]*\frac{3}{4} dp[i][j]=dp[i+1][j]∗41+dp[1][n−2]∗43
当 j = = 2 j==2 j==2
d p [ i ] [ j ] = d p [ i + 1 ] [ n − 2 ] ∗ 1 4 + d p [ 1 ] [ 1 ] ∗ 1 4 + d p [ 1 ] [ n − 1 ] ∗ 2 4 dp[i][j]=dp[i+1][n-2]*\frac{1}{4}+dp[1][1]*\frac{1}{4}+dp[1][n-1]*\frac{2}{4} dp[i][j]=dp[i+1][n−2]∗41+dp[1][1]∗41+dp[1][n−1]∗42
当 j = = 3 j==3 j==3
d p [ i ] [ j ] = d p [ i + 1 ] [ n − 1 ] ∗ 1 4 + d p [ 1 ] [ n − 1 ] ∗ 1 4 + d p [ 1 ] [ 1 ] ∗ 1 4 + d p [ 1 ] [ n ] ∗ 1 4 dp[i][j]=dp[i+1][n-1]*\frac{1}{4}+dp[1][n-1]*\frac{1}{4}+dp[1][1]*\frac{1}{4}+dp[1][n]*\frac{1}{4} dp[i][j]=dp[i+1][n−1]∗41+dp[1][n−1]∗41+dp[1][1]∗41+dp[1][n]∗41
当 j = = 4 j==4 j==4
d p [ i ] [ j ] = d p [ i + 1 ] [ n ] ∗ 1 4 + d p [ 1 ] [ 1 ] ∗ 1 4 + d p [ 1 ] [ n ] ∗ 2 4 dp[i][j]=dp[i+1][n]*\frac{1}{4}+dp[1][1]*\frac{1}{4}+dp[1][n]*\frac{2}{4} dp[i][j]=dp[i+1][n]∗41+dp[1][1]∗41+dp[1][n]∗42
且初始状态也很容易算
d p [ m ] [ 1 ] = 1 , d p [ m ] [ j ] = 0 ( j ! = 1 ) dp[m][1]=1,dp[m][j]=0(j!=1) dp[m][1]=1,dp[m][j]=0(j!=1)
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-10;
const int maxn=109;
int cnt,n,m,k;
double x[maxn],g[maxn][maxn];
void r(int i,int j,double val)
{
if( i==m )
{
if( j==1 ) g[cnt][m*n+1]+=-val;
return;
}
g[cnt][i*n+j]+=val;
}
void gauss(int n,int m)
{
int row,col,i,j,k;
for(row=1,col=1;row<n,col<m;row++,col++)
{
k=row;
for(i=row+1;i<=n;i++) //列主元
if(fabs(g[i][col])>fabs(g[k][col]))
k=i;
if(k!=row) //行交换
{
for(i=col; i<=m; i++)
swap(g[k][i],g[row][i]);
}
for(i=row+1; i<=n; i++) //主元不是0把下面的行第一个值全部变为0
{
if(fabs(g[i][col])<eps)
continue;
double t=g[i][col]/g[row][col];
g[i][col]=0.0;
for(j=col+1;j<=m;j++)
g[i][j]-=t*g[row][j];
}
}
for(i=n;i>=1;i--) //回代求解
{
x[i]=g[i][m];
for(j=i+1;j<=n;j++)
x[i]-=x[j]*g[i][j];
x[i]/=g[i][i];
}
}
int main()
{
//连续赢m次比赛才行
int casenum=0,t;
cin >> t;
while( t-- )
{
cin >> n >> m >> k;
memset(g,0,sizeof(g));
for(int i=0;i<m;i++)//赢得比赛场次
for(int j=1;j<=n;j++)
{
cnt++; r(i,j,1.0);
if( j==1 )
r(i+1,j,-0.25), r(1,n-2,-0.75);
else if( j==2 )
r(i+1,n-2,-0.25), r(1,1,-0.25), r(1,n-1,-0.5);
else if( j==3 )
{
r(i+1,n-1,-0.25), r(1,n-1,-0.25);
r(1,1,-0.25), r(1,n,-0.25);
}
else if( j==4 )
r(i+1,n,-0.25), r(1,1,-0.25), r(1,n,-0.5);
else
r(i+1,j-3,-0.25), r(1,j-3,-0.75);
}
gauss(cnt,cnt+1);
printf("Case #%d: %.6lf\n",++casenum,x[k]);
cnt=0;
}
}