LA 4731

时间:2022-10-17 12:14:16

dp[i][j]意思是前i个分成j组最小的花费

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define maxn 110
using namespace std; int dp[maxn][maxn];
int vis[maxn][maxn];
int num[maxn];
int sum[maxn]; bool cmp(int a,int b)
{
return a>b;
} int get(int a,int b)
{
// printf("%d %d---\n",a,b);
if(vis[a][b])return dp[a][b];
int& ans=dp[a][b];
ans=;
vis[a][b]=;
for(int i=b-; i<a; i++)
{
ans=min(ans,get(i,b-)+(sum[a]-sum[i])*a);
}
return ans;
} int main()
{
int t,n,w;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&w);
int all=;
for(int i=; i<=n; i++)
{
scanf("%d",&num[i]);
all+=num[i];
}
sort(num+,num+n+,cmp); for(int i=; i<=n; i++)
sum[i]=sum[i-]+num[i]; memset(vis,,sizeof vis); for(int i=; i<=n; i++)
{
vis[i][i]=;
dp[i][i]=dp[i-][i-]+num[i]*i;
vis[i][]=;
dp[i][]=sum[i]*i;
} int ans=get(n,w); printf("%.4lf\n",((double)ans/(double)all));
}
return ;
}