acwing 104.货仓选址
题意:需要在竖轴上选一个点,使该点到其他给出点的距离之和最小。将其抽象为数学公式$\left | x - c_1 \right |+\left | x-c_2 \right |+\left | x-c_3 \right |+\cdot \cdot \cdot \left | x-c_k \right |$,求该公式的最小值。
可以知道,该公式的最小值就是取$c_1, c_2, c_3,\cdot \cdot \cdot c_k$的中位数。
证明:
当只有一个点的时候,选在该点肯定为最小,当有两个点的时候,选在两个点中间的任何一个位置都为最小,当有三个点的时候,选在中间那个点的位置。我们将每个点两两分组。
①当$k$为奇数时,$x_1$和$x_k$一组,$x_2$和$x_{k -1}$一组,最后剩$x_{\fact_{k + 1}{2}}$单独一组,可以知道,选择每一组中间的点都是最小的。而$x_{\fact_{k + 1}{2}}$这一组要选在这个点上最小,所以选在$x_{\fact_{k + 1}{2}}$上的时候,满足该组的值最小,也满足其他组的值最小,所以总和最小。
②当$k$为偶数时,每一组都是两两配对,选择每组中间的位置就最小值,而最靠近中心的两个点的那个区间,选择任意一个在该区间内的点,都可以做到使得每一组的答案最小。
思路:读入一个$a$数组,排序,找出中位数,用所有数减去中位数的绝对值相加即为答案。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int N = 1e5+10; 8 int a[N]; 9 int n; 10 11 int main(){ 12 cin >> n; 13 for(int i = 0 ; i < n ; i ++)cin >> a[i]; 14 15 sort(a, a + n); 16 int c = a[n / 2]; 17 18 int res = 0; 19 for(int i = 0 ; i < n ; i ++)res += abs(a[i] - c); 20 21 cout << res << endl; 22 return 0; 23 }