P2503 [HAOI2006]均分数据 题解(随机贪心)

题目链接

题目大意

把n个数分为m组

每一组相当于一个新的数,为这组所有数之和

求这m个数的均方差最小

\(m<=n<=20,2 <=m <= 6\)
image-20210125131719567

题目思路

本来我一直是把数大的先放,然后数小的后放,疯狂贪心

结果还是只能过60%

其实可以直接随机数组,然后贪心

每次直接放在最小的那个组里面

因为显然每个数尽量接近使得均方差最少

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=20+5,inf=0x3f3f3f3f;
const int eps=1e-6;
int n,m;
int a[maxn];
int zu[7];
double ans=inf;
int main(){
    scanf("%d %d",&n,&m); //n<=20 2<=m<=6
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int _=1e6;
    while(_--){
        memset(zu,0,sizeof(zu));
        random_shuffle(a+1,a+1+n);
        for(int i=1;i<=n;i++){
            int mi=1;
            for(int j=1;j<=m;j++){ //让最小的那组+a[i]
                if(zu[j]<zu[mi]){
                    mi=j;
                }
            }
            zu[mi]+=a[i];
        }
        double sum=0,cal=0;
        for(int i=1;i<=m;i++){
            sum+=zu[i];
        }
        sum/=m;
        for(int j=1;j<=m;j++){
            cal+=1.0/m*(zu[j]-sum)*(zu[j]-sum);
        }
        ans=min(ans,sqrt(cal));
    }
    printf("%.2f\n",ans);
    return 0;
}

posted @ 2021-01-25 13:24  hunxuewangzi  阅读(66)  评论(0编辑  收藏  举报