/**//* 题意:数轴上有n个点,给出这n个点的坐标,求最少的移动距离使得所有点等距排列(不改变原来的相对顺序) 跟士兵站队类似,但这里两个点之间的距离avg不知道,可以通过枚举出来 考虑到,avg太大也不行,太小也不行,应该是一种抛物线,用三分枚举 设第0个点的新位置为x0,则 _x[i] = x0 + i*avg 移动总距离 sum = ∑|x[i]-_x[i]| = ∑|x[i]-x0-i*avg| = ∑|(x[i]-i*avg)-x0| 设y[i] = (x[i]-i*avg) ,则可以用中位数定理,求出x0 = y[n/2] */ #include<iostream> #include<cmath> #include<algorithm> #include<cstdio> #include<iomanip>
using namespace std;
const double EPS = 1e-8;
double x[410] , y[410] , x0; int n ;
double cal(double avg) { for(int i = 0; i < n; i++) y[i] = x[i] - i * avg; sort(y,y+n);//需要sort double sum = 0 ; x0 = y[n/2]; for(int i = 0; i<n;i++) { sum += fabs(y[i]-x0); } return sum; }
int main() { //freopen("in","r",stdin); while(~scanf("%d",&n)) { double left = 0.0 , right = 100000.0; for(int i = 0 ; i < n ; i++) { scanf("%lf",&x[i]); } while(right - left > EPS) { double gap = (right - left)/3; double m1 = left + gap ; double m2 = right - gap ; if(cal(m1) + EPS < cal(m2))right = m2; else left = m1; } printf("%.4f\n",cal(left)); for(int i = 0; i < n;i++) { if(i)putchar(' '); printf("%.7f",x0+i*left); } puts(""); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|