 /**//*
題意:數(shù)軸上有n個點,給出這n個點的坐標(biāo),求最少的移動距離使得所有點等距排列(不改變原來的相對順序)
跟士兵站隊類似,但這里兩個點之間的距離avg不知道,可以通過枚舉出來
考慮到,avg太大也不行,太小也不行,應(yīng)該是一種拋物線,用三分枚舉
設(shè)第0個點的新位置為x0,則
_x[i] = x0 + i*avg
移動總距離 sum = ∑|x[i]-_x[i]| = ∑|x[i]-x0-i*avg| = ∑|(x[i]-i*avg)-x0|
設(shè)y[i] = (x[i]-i*avg) ,則可以用中位數(shù)定理,求出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
搜索
最新評論

|
|