problem
- 平面上有N(N<=10000)个点
- 求这些点变成一条水平线的最小移动步数
solution
- 对于y轴,易证得在中位数处取到最优,直接排序统计即可。
- 对于x轴,因为要保证相对顺序,(比如:原来三个士兵的x坐标是 -1 5 6,那么在他们移动之后,假设移动成一条直线之后,起点是原来-1的那个士兵,现在的坐标是9,那么他们之间的相对位置就是9 10 11…)
1、假设最后水平线的起点是a,根据上面的理论可以得到 x’[0] = a, x’[1] = a+1, x’[2] = a+2…
2、移项,可以得到x[0] - 0 = a, x[1] - 1 = a, x[2] - 2 = a…..
3、所以我们把每个x[i] 都减去i,然后再从小到大排序,这样就保证在相对位置不变的情况下成一条水平线。然后把距离差求和就可以了。
codes
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int a[10010], b[10010];
int main(){
int n; cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i]>>b[i];
sort(b+1,b+n+1);
int y = b[n+1>>1];
sort(a+1,a+n+1);
for(int i = 1; i <= n; i++)a[i]-=i;
sort(a+1,a+n+1);
int x = a[n+1>>1];
int ans = 0;
for(int i = 1; i <= n; i++)
ans += abs(a[i]-x)+abs(b[i]-y);
cout<<ans<<'\n';
return 0;
}