从大到小排个序,然后随便dp一下就出来了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
double dp[maxn][maxn];
int T, n, m, a[maxn];
double p[maxn], sum[maxn];
bool cmp(double x, double y) { return x > y; }
void solve() {
scanf("%d%d", &n, &m);
int s = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), s += a[i];
for (int i = 1; i <= n; i++) p[i] = 1.0*a[i]/s;
sort(p+1, p+1+n, cmp);
sum[0] = 0;
for (int i = 1; i <= n; i++) sum[i] = sum[i-1] + p[i];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = INF;
}
}
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i && j <= m; j++) {
for (int k = j-1; k <= i-1; k++) {
dp[i][j] = min(dp[i][j], dp[k][j-1] + (sum[i]-sum[k])*i);
}
}
}
printf("%.4f\n", dp[n][m]);
}
int main() {
scanf("%d", &T);
while (T--) solve();
return 0;
}