题意:
一个棋盘如果每行每列都有棋子那么这个棋盘达到目标状态 现在随机放棋子 问达到目标状态的期望步数
思路:
用概率来做 计算第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; }
原文地址:http://blog.csdn.net/houserabbit/article/details/40077261