话说这题读起来真费劲啊,估计很多人做不出来就是因为题读不懂......
从题目中提取的几点关键点:
题目背景就是银河系(Rho Galaxy)中的星球都是绕着他们的质心(center of mass)转的(妈蛋就是这里啊,质心是个什么鬼...,其实就是所有点的值的算术平均值)。
现在你可以从一个银河系中的所有星球中转移其中的k个(具体这个转移的意思你可以理解成把他们移到剩下星球的质心上,这样对剩余的整体不会产生影响,当然这也等价于把这k个星球直接删了),然后使剩下的星球让这个The moment of inertia I值最小,计算公式是
其中wi是每个星球的重量,视为单位1,di是星球i到质心的距离(di-d0)。
这样看来I值就是(d1-d0)2 + (d2-d0)2 + ... + (dn-k-d0)2
这不就是标准差吗,当然标准差就是方差的平方,而方差越小表示分布越集中,也就是说,这些星球越连续,这个I值就会越小。
因此这里也用到了贪心的思想。
需要注意的一点是,当n=k时,可以直接输出0,因为这孩子把所有星球都弄到质心去了2333333...
附代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 using namespace std; 8 typedef long long ll; 9 const int maxn = 500005; 10 ll a[maxn]; 11 12 int main() 13 { 14 int T; scanf("%d", &T); 15 while(T--) 16 { 17 int n, k; scanf("%d%d", &n, &k); 18 for(int i = 0; i < n; i++) 19 scanf("%I64d", &a[i]); 20 sort(a, a+n); 21 ll sum1, sum2; sum1 = sum2 = 0; 22 double cen, ans; 23 if(n == k) 24 { 25 for(int i = 0; i < n; i++) 26 { 27 sum1 += a[i]*a[i]; 28 sum2 += a[i]; 29 } 30 cen = (double)sum2/n; 31 ans = sum1+n*cen*cen-2*cen*sum2; 32 printf("%.10lf\n", ans); 33 //cout << ans << endl; 34 continue ; 35 } 36 for(int i = 0; i < n-k; i++) 37 { 38 sum1 += a[i]*a[i]; 39 sum2 += a[i]; 40 } 41 cen = 1.0*sum2/(n-k); 42 ans = sum1+(n-k)*cen*cen-2*cen*sum2; 43 int pos = 0; 44 double min_ = ans; 45 for(int i = 0; i < k; i++) 46 { 47 sum1 = sum1-a[i]*a[i]+a[n-k+i]*a[n-k+i]; 48 sum2 = sum2-a[i]+a[n-k+i]; 49 cen = 1.0*sum2/(n-k); 50 ans = sum1+(n-k)*cen*cen-2*cen*sum2; 51 min_ = min(min_, ans); 52 } 53 printf("%.10lf\n", min_); 54 } 55 return 0; 56 }
hdu 5037
时间: 2024-10-09 10:24:34