hdu5073Galaxy dp
2015-10-12 21:35
211 查看
//n个数,最多移动k个数,使得这 //n个数的segment((xi - X)^2)(1<=i<=n) //其中X为这n个数的平均数 //可以考虑将k个数移动到剩下的(n-k)个数的 //平均数中,然后就相当于,从n中选k个数其方差最小 //然后可以将这n个数排一下序,选的n-k的数一定是 //连续的,这个应该比较容易想到,然后 //dp[i] 表示最后一个数为i的连续n-k个数方差 //然后记录一下sum(这n-k个数的和)就能更新 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> using namespace std ; const int maxn = 1e5+10 ; double a[maxn] ; double dp[maxn] ; int main() { int t ; scanf("%d" , &t) ; while(t--) { int n , k ; scanf("%d%d" , &n , &k) ; for(int i = 1;i <= n;i++) scanf("%lf" , &a[i]) ; sort(a+1 , a+1+n) ; if(k == n) { puts("0") ; continue ; } memset(dp , 0 , sizeof(dp)) ; double sum = 0 ; for(int i = 1;i <= n-k;i++) sum += a[i] ; for(int i = 1;i <= n-k;i++) dp[n-k] += (a[i]*(n-k)-sum)*((n-k)*a[i]-sum) ; double ans = dp[n-k] ; for(int i = n-k;i < n;i++) { int j = i-(n-k) + 1 ; double tmp1 = pow(((n-k)*a[j]-sum)*1.0 , 2) ; double tmp2 = 2*((a[j]-a[i+1])*(n-k)*(sum-a[j])) ; double tmp3 = (n-k-1)*pow((a[j]-a[i+1])*1.0,2) ; double tmp4 = pow(((n-k)*a[i+1]-(sum-a[j]+a[i+1]))*1.0 , 2) ; dp[i+1] = dp[i] - tmp1 + tmp2 +tmp3 + tmp4; double tmp = 2*(a[j] - a[i+1])*sum*(n-k-1) ; dp[i+1] -= tmp ; ans = min(ans , dp[i+1]) ; sum = sum - a[j] + a[i+1] ; } printf("%.9lf\n" , ans/((n-k)*(n-k)*1.0)) ; } return 0 ; }
相关文章推荐
- UVALive 7037 The Problem Needs 3D Arrays(最大密度子图)
- 利用Android studio快速搭建安卓开发环境
- 【黑马程序员】【C语言】循环结构-while语句
- 《剑指Offer》面试题:数组中只出现一次的数字
- having用法
- vijosP1543 极值问题
- ios设备 分辨率(转)
- hdu3672 Caves 树形dp
- git(学习之三)基本操作
- 【黑马程序员】【C语言】选择结构-switch语句
- codevs 1159 最大全0子矩阵
- 设计模式漫谈
- hdu3672 Caves 树形dp
- delphi创建服务程序
- iOS后台模式开发指南
- C语言第一天
- MVC中Action之间传值
- eclipse java工程和maven工程的互相转换
- 只有程序员看的懂面试圣经
- LINUX 环境下源码方式安装mysql5.6