题目描述
在一条数轴上有 NNN 家商店,它们的坐标分别为 A1A_1A1∼ANA_NAN。
现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。
为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。
输入格式
第一行输入整数 NNN。
第二行 NNN 个整数 A1A_1A1∼ANA_NAN。
输出格式
输出一个整数,表示距离之和的最小值。
数据范围
1≤N≤1000001≤N≤1000001≤N≤100000,
0≤Ai≤400000≤A_i≤400000≤Ai≤40000
输入样例
4
6 2 9 1
输出样例
12
解题思路(绝对值不等式)
设f(x)f(x)f(x)表示把货仓建在xxx位置时距离之和的最小值,那么:
f(x)=∣X1−x∣+∣X2−x∣+...+∣Xn−x∣f(x) = |X_1 - x| + |X_2 - x| + ... + |X_n - x|f(x)=∣X1−x∣+∣X2−x∣+...+∣Xn−x∣
分组,将第一项和最后一项分一组,第二项和倒数第二项一组…,那么
f(x)=(∣X1−x∣+∣Xn−x∣)+(∣X2−x∣+∣Xn−1−x∣)+...f(x) = (|X_1 - x| + |X_n - x|) + (|X_2 - x| + |X_{n-1} - x|) + ...f(x)=(∣X1−x∣+∣Xn−x∣)+(∣X2−x∣+∣Xn−1−x∣)+...
因为:
∣X1−x∣+∣Xn−x∣>=Xn−X1...|X_1 - x| + |X_n - x| >= X_n - X_1 ...∣X1−x∣+∣Xn−x∣>=Xn−X1...
所以:
f(x)>=Xn−X1+Xn−1−X2...f(x) >= X_n - X_1 + X_{n-1} - X_2...f(x)>=Xn−X1+Xn−1−X2...
如果
f(x)=Xn−X1+Xn−1−X2...,f(x) = X_n - X_1 + X_{n-1} - X_2...,f(x)=Xn−X1+Xn−1−X2...,
则f(x)f(x)f(x)为最小值。那么 xxx 建在中位数的位置,即a[n/2]a[n / 2]a[n/2]时,满足距离之和的最小值。此时a[n/2]a[n / 2]a[n/2]为序列的中位数。
中位数(Median)又称中值,指按顺序排列的一组数据中居于中间位置的数。
代码实现
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 100010;
int a[N];
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
sort(a, a + n);
int res = 0;
for(int i = 0; i < n; i++) res += abs(a[i] - a[n / 2]);
printf("%d\n", res);
return 0;
}