【问题描述】
用C++解决。小明和小亮在玩一个石子游戏。刚开始,小明有n堆石子,小亮有m堆石子。且两人每一堆石子所包含的石子个数均不超过6。
现在,小明需要执行d次魔法操作。每次魔法操作会从当前还剩余的几堆石子中随机选择一堆(选择每一堆的概率相同),并从这一堆中去掉一个石子。
如果某一堆经过一次魔法操作后不再有任何石子,那么在下次魔法操作执行时则不会再考虑这一堆。
现在小明想知道,在经过d次魔法操作之后,小亮一堆石子都不剩的概率是多少?
【输入形式】
输入的第一行包含三个整数n,m和d(1 ≤ n, m ≤ 5; 1 ≤ d ≤ 100)。
接下来一行包含n个整数,表示小明每堆石子的初始石子数。
第三行包含m个整数,表示小亮每堆石子的初始石子数。所有石子数都在1到6之间(包括1和6)。
【输出形式】
输出经过d次魔法操作后,小亮一堆石子都不剩的概率。结果保留四位小数。
【样例输入】
1 2 2
2
1 1
【样例输出】
0.3333
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 5;
const int MAXM = 5;
const int MAXS = 6;
const int MAXD = 100;
const int MAXS2 = MAXS * MAXS * MAXS * MAXS * MAXS * MAXS;
double dp[2][MAXS2 + 10];
int n, m, d;
vector<int> a, b;
int get_idx(const vector<int>& v) {
int res = 0;
for (int i = 0; i < v.size(); i++) {
res = res * MAXS + v[i];
}
return res;
}
vector<int> get_vec(int idx, int size) {
vector<int> res;
while (size--) {
res.push_back(idx % MAXS);
idx /= MAXS;
}
return res;
}
int main() {
cin >> n >> m >> d;
a.resize(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
b.resize(m);
for (int i = 0; i < m; i++) {
cin >> b[i];
}
memset(dp, 0, sizeof(dp));
int cur = 0, nxt = 1;
dp[cur][get_idx(b)] = 1.0;
for (int t = 0; t < d; t++) {
memset(dp[nxt], 0, sizeof(dp[nxt]));
for (int i = 0; i < MAXS; i++) { // 选择哪一堆石子
vector<int> tmpa = a;
if (tmpa[i] > 0) {
tmpa[i]--;
for (int j = 0; j < MAXS; j++) {
vector<int> tmpb = b;
if (tmpb[j] > 0) {
tmpb[j]--;
int nxt_idx = get_idx(tmpb);
dp[nxt][nxt_idx] += dp[cur][get_idx(tmpa)] / (n * m);
}
}
}
}
cur ^= 1;
nxt ^= 1;
}
double ans = 0.0;
for (int i = 0; i < MAXS2; i++) {
vector<int> tmpb = get_vec(i, m);
bool flag = true;
for (int j = 0; j < m; j++) {
if (tmpb[j] > 0) {
flag = false;
break;
}
}
if (flag) {
ans += dp[cur][i];
}
}
cout << fixed << setprecision(4) << ans << endl;
return 0;
}