[ABC332E] Lucky bag 题解
先推一推式子:
于是你只需要最小化
考虑状压 dp,设
直接做即可,时间复杂度
特别要注意的是你输出答案时应当只在最后进行一次 long double 下的除法,之前的运算都应在整数下进行,否则精度误差能直接给你爆了。
#include <iomanip>
#include <iostream>
using namespace std;
using LL = long long;
const int kN = 15;
int n, d, w[kN];
LL f[kN + 1][1 << kN], s[1 << kN];
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> d;
for (int i = 0; i < n; ++i) {
cin >> w[i];
for (int j = 0; j < (1 << n); ++j) {
if (j >> i & 1) {
s[j] += w[i];
}
}
}
for (int i = 0; i < (1 << n); ++i) {
s[i] *= s[i];
}
for (int i = 1; i < (1 << n); ++i) {
f[0][i] = 3e18;
}
for (int i = 1; i <= d; ++i) {
for (int j = 0; j < (1 << n); ++j) {
f[i][j] = s[j];
for (int k = j; k; k = j & k - 1) {
f[i][j] = min(f[i][j], f[i - 1][k] + s[j ^ k]);
}
}
}
cout << fixed << setprecision(15) << 1.0L * (f[d][(1 << n) - 1] * d - s[(1 << n) - 1]) / (d * d);
return 0;
}