[SCOI2008]奖励关
Description
Solution
状压DP,倒着来,\(f[i][S]\)表示前\(i-1\)个选了\(S\),\(i\)到\(k\)的最大收益。
Code
const int N = 20;
const int MXS = (1 << 17);
int pre[N], k, n, a[N];
double F[110][MXS];
void main() {
k = read(), n = read();
for (int i = 1; i <= n; ++i) {
a[i] = read();
int x;
while ((x = read()) != 0) pre[i] |= (1 << x);
}
for (int i = k; i; --i) {
for (int S = 0; S < MXS; ++S) {
for (int j = 1; j <= n; ++j)
if ((S & pre[j]) == pre[j]) {
F[i][S] +=
std::max(F[i + 1][S | (1 << j)] + a[j], F[i + 1][S]);
} else
F[i][S] += F[i + 1][S];
F[i][S] /= n;
}
}
printf("%.6lf\n", F[1][0]);
}