自爆魂

博客园 首页 新随笔 联系 订阅 管理

http://acm.hdu.edu.cn/showproblem.php?pid=5073

就是给你 n 个数,代表n个星球的位置,每一个星球的重量都为 1
开始的时候每一个星球都绕着质心转动,那么质心的位置就是所有的星球的位置之和 / 星球的个数
现在让你移动 k 个星球到任意位置(多个星球可以在同一个位置并且所有的星球在同一直线上)
移动之后那么它们质心的位置就可能发生变化,求 I = sum(di^2) (di表示第i个星球到达质心的距离)最小


根据方差的性质(越密越小)得知贪心策略就是,n-k序列一定连续,那么随即求连续n-k序列里面方差最小的那个

设连续长度为k

avg = sum/k;

有 求和(pi - avg)^2 = (求和pi^2)   -  sum^2/k;

然后贪心模拟一遍即可

输入序列式无序的,样例坑到死,不sort或者sum^2/k精度问题WA到死


#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%I64d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
const int maxn = 5e4+5;
const double INF = 1e20;
int n,k;
LL p[maxn],sum[maxn],sq[maxn];
int main() {
    int _;RD(_);while(_--){
        RD2(n,k);
        p[0] = sum[0] = sq[0] = 0;
        for(int i = 1;i <= n;++i)
            RD(p[i]);
        double ans = INF;
        k = n - k;
        if(k == 0 || k == 1){
            puts("0");
            continue;
        }
        sort(p+1,p+n+1);
        for(int i = 1;i <= n;++i)
            sum[i] = p[i] + sum[i-1],sq[i] = p[i]*p[i] + sq[i-1];
        for(int i = k;i <= n;++i)
            ans = min(ans,(double)(sq[i] - sq[i - k])*(double)k - (double)(sum[i] - sum[i-k])*(double)(sum[i] - sum[i-k]));
        printf("%.10lf\n",ans/(double)k);
    }
    return 0;
}


posted on 2014-10-23 13:45  自爆魂  阅读(163)  评论(0编辑  收藏  举报