题目链接
题意
n*m的棋盘,占领一个格子可以控制这个行和列,每天随机占领一个格子直到控制所有行列。
求控制所有行列所需要占领格子的天数期望。
思路
DP开三个维度,DP[k][i][j],k表示天数,i表示已占领行数量,j表示已占领列数量
DP表示距离终点的期望
我们可以从终点倒着推,所有终点的期望都是0
dp[k] 可以由 dp[k+1] 推来
DP[K][I][J]的期望即下面五个式子之和
概率 * DP[K+1][I][J],到后一天控制不变
概率 * DP[K+1][I+1][J],到后一天多控制了一行
概率 * DP[K+1][I][J+1],到后一天多控制了一列
概率 * DP[K+1][I+1][J+1],到后一天多控制了一行和一列
1.0,到后一天花了一点期望
概率可以画个2*2的小方格瞎搞一下推得(具体概率见代码)。
代码
#include <stdio.h>
#include <string.h>
double dp[2][55][55];
int main()
{
int t;
for(scanf("%d",&t); t; --t)
{
int n, m, cur = 0;
scanf("%d%d",&n,&m);
memset(dp[cur],0,sizeof(dp[cur]));
for(int k = n*m-1; ~k; --k)
{
cur ^= 1;
memset(dp[cur],0,sizeof(dp[cur]));
for(int i = 0; i <= n; ++i)
{
for(int j = 0; j <= m; ++j)
{
if(i == n && j == m) continue;
if(k > i*j || (k < i && k < j)) continue;
dp[cur][i][j] += dp[cur^1][i][j] * (i*j-k)/(n*m-k);
dp[cur][i][j] += dp[cur^1][i+1][j] * ((n-i)*j)/(n*m-k);
dp[cur][i][j] += dp[cur^1][i][j+1] * ((m-j)*i)/(n*m-k);
dp[cur][i][j] += dp[cur^1][i+1][j+1] * (n-i)*(m-j)/(n*m-k);
dp[cur][i][j] += 1.0;
}
}
}
printf("%.12lf\n",dp[cur][0][0]);
}
return 0;
}