题意
有 n n n个人,每个人投支持的概率为 p i p_i pi ,从中选出 k k k个人,使平票概率最大。
思路
由题解得出结论
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为前
i
i
i个人有
j
j
j个投支持,可得:
f
i
,
j
=
f
i
−
1
,
j
−
1
∗
p
i
+
f
i
−
1
,
j
∗
(
1
−
p
i
)
f_{i,j}=f_{i-1,j-1}*p_i+f_{i-1,j}*(1-p_i)
fi,j=fi−1,j−1∗pi+fi−1,j∗(1−pi)
最后枚举选的方案即可。
代码
#include <cstdio>
#include <algorithm>
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
int n, k;
double ans;
double p[2001], f[2001][2001], g[2001][2001];
int cmp(double a, double b) {
return a > b;
}
int main() {
file(vote);
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%lf", &p[i]);
std::sort(p + 1, p + n + 1);
f[0][0] = 1;
for (int i = 1; i <= k; i++)
for (int j = 0; j <= i; j++)
if (j) f[i][j] = f[i - 1][j - 1] * p[i] + f[i - 1][j] * (1 - p[i]);
else f[i][j] = f[i - 1][j] * (1 - p[i]);
std::sort(p + 1, p + n + 1, cmp);
g[0][0] = 1;
for (int i = 1; i <= k; i++)
for (int j = 0; j <= i; j++)
if (j) g[i][j] = g[i - 1][j - 1] * p[i] + g[i - 1][j] * (1 - p[i]);
else g[i][j] = g[i - 1][j] * (1 - p[i]);
for (int i = 0; i <= k; i++) {
double tmp = 0;
for (int j = 0; j <= k / 2; j++) tmp += f[i][j] * g[k - i][k / 2 - j];
ans = std::max(ans, tmp);
}
printf("%.6lf", ans);
}