题意:
一个棋盘如果每行每列都有棋子那么这个棋盘达到目标状态 现在随机放棋子 问达到目标状态的期望步数
思路:
用概率来做 计算第k步达到目标状态的概率 进而求期望 概率计算方法就是dp dp[k][i][j]表示第k步有i行被覆盖j列被覆盖 转移只有4种 —— 同时覆盖行列 覆盖行 覆盖列 不覆盖 状态数50^4 很简单
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 55
int t, n, m;
double dp[N * N][N][N], ans;
int main() {
int i, j, k;
scanf("%d", &t);
while (t--) {
memset(dp, 0, sizeof(dp));
dp[0][0][0] = 1;
ans = 0;
scanf("%d%d", &n, &m);
for (k = 1; k <= n * m; k++) {
for (i = 0; i <= n; i++) {
for (j = 0; j <= m; j++) {
if (i == n && j == m)
break;
int f00 = i * j - k + 1;
int f01 = i * (m - j);
int f10 = (n - i) * j;
int f11 = (n - i) * (m - j);
int sum = n * m - k + 1;
dp[k][i][j] += dp[k - 1][i][j] * f00 / sum;
dp[k][i + 1][j] += dp[k - 1][i][j] * f10 / sum;
dp[k][i][j + 1] += dp[k - 1][i][j] * f01 / sum;
dp[k][i + 1][j + 1] += dp[k - 1][i][j] * f11 / sum;
}
}
ans += dp[k][n][m] * k;
}
printf("%.10f\n", ans);
}
return 0;
}