题意:每次选一个格子,放一个球,一个球能控制它所在的行和列,求控制所有整个矩阵球的期望个数。
思路分析:由于矩阵只有50*50 , 枚举球的个数即可,dp[i][j][k]表示用k个球,控制了i行和j列的概率,
状态转移dp[i][j][k] = p1*dp[i-1][j][k-1] + p2*dp[i][j-1][k-1] + p3*dp[i-1][j-1][k-1] + p4*dp[i][j][k-1];
最后期望就是dp[n][m][0--n*m]。
代码如下:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#define N 55
using namespace std;
double dp[N][N][N*N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(dp,0,sizeof(dp));
dp[0][0][0] = 1.0;
int i,j,k;
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
for(k = 1; k <= n*m; k++)
{
if(k > i*j) break;
if(k < max(i,j)) continue;
double p1 = 1.0*(n-i+1)*j/(1.0*(n*m-k+1) );
double p2 = 1.0*(m-j+1)*i/(1.0*(n*m-k+1) );
double p3 = 1.0*(n-i+1)*(m-j+1)/(1.0*(m*n-k+1) );
double p4 = 1.0*( i*j-k+1 )/(1.0*(n*m-k+1) );
if(i == n && j == m) p4 = 0;
dp[i][j][k] = p1*dp[i-1][j][k-1] + p2*dp[i][j-1][k-1] + p3*dp[i-1][j-1][k-1] + p4*dp[i][j][k-1];
}
double ans = 0;
int st = max(n,m);
int ed = n*m - min(n,m);
for(i = st; i <= n*m; i++)
ans += dp[n][m][i]*i;
printf("%.12lf\n",ans);
}
return 0;
}