版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83420036
题意:问期望多少天能把一个n*m的棋盘放成每一行每一列都至少有一个棋子的样子,一天只能放一个。
题解:动态规划,可以考虑
为i天放了i行和j列的概率,然后可以通过当前状态可以转移到下一天的概率。
如使
天 :
- 占i行和j列
- 占i+1行和j+1列
- 占i行j+1列
- 占i+1行j列
具体转移见代码。
收获:概率不是平均值,这也是为什么暴力的结果是2.8。
/**hqx is the best**/
/*****数组大小*****/
/**hqx is the best**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug cerr << "*" << endl;
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define pre(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 41 + 10;
const int inf = 0x3f3f3f3f;
int T, n, m;
double dp[maxn * maxn][maxn][maxn];
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
met(dp, 0.0);
dp[1][1][1] = 1.0;
for(int i = 1; i <= n * m; i++) {
for(int j = 1; j <= n; j++) {
for(int k = 1; k <= m; k++) {
dp[i + 1][j][k] += dp[i][j][k] * 1.0 * (j * k - i) / (double)(n * m - i);
dp[i + 1][j + 1][k] += dp[i][j][k] * 1.0 * ((n - j) * k) / (double)(n * m - i);
dp[i + 1][j][k + 1] += dp[i][j][k] * 1.0 * ((m - k) * j) / (double)(n * m - i);
dp[i + 1][j + 1][k + 1] += dp[i][j][k] * 1.0 * ((m - k) * (n - j)) / (double)(n * m - i);
}
}
}
double ans = 0.0;
for(int i = 1; i <= n * m; i++) {
ans += 1.0 * (dp[i][n][m] - dp[i - 1][n][m]) * i;
}
printf("%.10f\n", ans);
}
return 0;
}