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; }