您的位置:首页 > 其它

HDU 5073 Galaxy (贪心)

2015-10-10 21:18 501 查看
题意:

直线上n<=5×104个点,任意移动至多k<n个点到任意位置,求到质心的距离的ns2最小

分析:

I=∑ni=1wi∗d2i=∑ni=1(xi−avg)2=∑ni=1x2i−2∗∑ni=1xi∗avg+n∗avg

说白了,由于没方差没除n,那么最后剩下的点越少越好(ns2越小)

一定删掉k个点移动到新的质心,所以two pointers不断求n−k个点质心来做就好了

代码:

//
//  Created by TaoSama on 2015-10-10
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, k;
double x
;
double sq(double x) {return x * x;}

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i) scanf("%lf", x + i);
if(n == k) {
puts("0");
continue;
}

sort(x + 1, x + 1 + n);
int lef = n - k;
double sum = 0, sqsum = 0;
for(int i = 1; i <= lef; ++i) {
sum += x[i];
sqsum += sq(x[i]);
}
double avg = sum / lef;
double ans = sqsum + lef * sq(avg) - 2 * sum * avg;
for(int i = lef + 1; i <= n; ++i) {
sum += x[i]; sum -= x[i - lef];
sqsum += sq(x[i]); sqsum -= sq(x[i - lef]);
avg = sum / lef;
double tmp = sqsum + lef * sq(avg) - 2 * sum * avg;
ans = min(ans, tmp);
}
printf("%.12f\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  贪心