CF148D Bag of mice
题目传送门
思路
状态设计
设 \(dp_{i, j}\) 表示袋中有 \(i\) 个白鼠和 \(j\) 个黑鼠时,\(A\) 能赢的概率。
状态转移
现在考虑抓鼠情况:
- \(A\) 抓到白鼠:直接判 \(A\) 赢,概率是 \(\frac{i}{i + j}\);
- \(A,B\) 都抓到一只黑鼠,并且跑出来一只黑鼠:概率为 \(\frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{j - 2}{i + j - 2}\),然后转移到 \(dp_{i, j - 3}\),故此情况下 \(A\) 获胜的概率为 \(\frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{j - 2}{i + j - 2} \times dp_{i, j - 3}\);
- \(A,B\) 都抓到一只黑鼠,并且跑出来一只白鼠:概率为 \(\frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{i}{i + j - 2}\),然后转移到 \(dp_{i - 1, j - 2}\),故此情况下 \(A\) 获胜的概率为 \(\frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{i}{i + j - 2} \times dp_{i - 1, j - 2}\);
- \(B\) 抓到白鼠:此情况 \(A\) 失败,故不考虑。
所以总得转移方程就是:
\[dp_{i, j} = \frac{i}{i + j} + \frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{j - 2}{i + j - 2} \times dp_{i, j - 3} + \frac{j}{i + j} \times \frac{j - 1}{i + j - 1} \times \frac{i}{i + j - 2} \times dp_{i - 1, j - 2}
\]
当然转移的时候得分别判断【\(j\) 是否大于等于 \(3\)】和【\(i\) 是否大于等于 \(1\) 且 \(j\) 是否大于等于 \(2\)】。
边界条件
- 在没有老鼠或全是黑鼠的情况下,\(A\) 一定输,即:\(\forall i \in [0, m], \ dp_{0, i} = 0\);
- 在只有白鼠的情况下,\(A\) 一定赢,即:\(\forall i \in [1, n], \ dp_{i, 0} = 1\)。
复杂度
- 时间复杂度:\(O(n \times m)\);
- 空间复杂度:\(O(n \times m)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 7;
int n, m;
double dp[maxn][maxn];
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i <= m; ++i) dp[0][i] = 0; // 没有老鼠或只有黑鼠, B 赢
for (int i = 1; i <= n; ++i) dp[i][0] = 1; // 只有白鼠, A 赢
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
dp[i][j] += 1.0 * i / (i + j);
if (j >= 3) {
dp[i][j] += 1.0 * j / (i + j) * 1.0 * (j - 1) / (i + j - 1) *
1.0 * (j - 2) / (i + j - 2) * dp[i][j - 3];
}
if (i >= 1 && j >= 2) {
dp[i][j] += 1.0 * j / (i + j) * 1.0 * (j - 1) / (i + j - 1) *
1.0 * i / (i + j - 2) * dp[i - 1][j - 2];
}
}
}
printf("%.9lf\n", dp[n][m]);
return 0;
}

浙公网安备 33010602011771号