题解 P3239 【[HNOI2015]亚瑟王】
如果能够求出每张卡牌在所有
第一步推出,
再考虑第二张:
情况一:如果第
情况二:如果第
结合这个例子,可以得到,对于任意的
根据这个性质,就能想到一个DP模型:
2:不发动。那么前
因此,完整的转移方程为:
那么求
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 234, R = 143;
int n, r, d[N];
double p[N], f[N][R], g[N], pw[N][R];
void work() {
memset(f, 0, sizeof(f)); memset(g, 0, sizeof(g));
int i, j; scanf("%d%d", &n, &r);
for (i = 1; i <= n; i++) scanf("%lf%d", &p[i], &d[i]), pw[i][0] = 1;
if (!r) return (void) puts("0.0000000000");
for (i = 1; i <= n; i++) for (j = 1; j <= r; j++)
pw[i][j] = pw[i][j - 1] * (1.0 - p[i]);
f[1][0] = pw[1][r]; f[1][1] = g[1] = 1.0 - pw[1][r];
for (i = 2; i <= n; i++) for (j = 0; j <= min(i, r); j++) {
if (j) f[i][j] += f[i - 1][j - 1] * (1.0 - pw[i][r - j + 1]);
if (i != j) f[i][j] += f[i - 1][j] * pw[i][r - j];
}
for (i = 2; i <= n; i++) for (j = 0; j <= min(i - 1, r); j++)
g[i] += f[i - 1][j] * (1.0 - pw[i][r - j]);
double ans = 0;
for (i = 1; i <= n; i++) ans += g[i] * d[i];
printf("%.10lf\n", ans);
}
int main() {
int T; cin >> T; while (T--) work();
return 0;
}