题目
题目描述
在一条数轴上有 N N N 家商店,它们的坐标分别为 A 1 ∼ A N A_1 \sim A_N A1∼AN。
现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。
为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。
输入格式
第一行输入整数 N N N。
第二行 N N N 个整数 A 1 ∼ A N A_1 \sim A_N A1∼AN。
输出格式
输出一个整数,表示距离之和的最小值。
样例 #1
样例输入 #1
4
6 2 9 1
样例输出 #1
12
提示
数据保证, 1 ≤ N ≤ 100000 1 \le N \le 100000 1≤N≤100000, 0 ≤ A i ≤ 40000 0 \le A_i \le 40000 0≤Ai≤40000。
做法
首先,如果设最后选择的地址为
x
x
x ,那么距离和为
∣
a
1
−
x
∣
+
∣
a
2
−
x
∣
+
∣
a
3
−
x
∣
+
.
.
.
+
∣
a
n
−
x
∣
|a_1 - x| + |a_2 - x| + |a_3 - x| + ... + |a_n - x|
∣a1−x∣+∣a2−x∣+∣a3−x∣+...+∣an−x∣
其次,我们把这个式子两两分组,分
n
n
n 为奇数和偶数两种情况看
n n n 为奇数时
原式
=
(
∣
a
1
−
x
∣
+
∣
a
n
−
x
∣
)
+
(
∣
a
2
−
x
∣
+
∣
a
n
−
1
−
x
∣
)
+
.
.
.
+
(
∣
a
(
n
+
1
)
/
2
−
1
−
x
∣
+
∣
a
(
n
+
1
)
/
2
+
1
−
x
∣
)
+
∣
a
(
n
+
1
)
/
2
−
x
∣
= (|a_1 - x| + |a_n - x|) + (|a_2 - x| + |a_{n - 1} - x|) + ... + (|a_{(n + 1) / 2 - 1} - x| + |a_{(n + 1) / 2 + 1} - x|) + |a_{(n + 1) / 2} - x|
=(∣a1−x∣+∣an−x∣)+(∣a2−x∣+∣an−1−x∣)+...+(∣a(n+1)/2−1−x∣+∣a(n+1)/2+1−x∣)+∣a(n+1)/2−x∣
上面的式子的最小值为
(
a
n
−
a
1
)
+
(
a
n
−
1
−
x
)
+
.
.
.
+
(
a
(
n
+
1
)
/
2
+
1
−
a
(
n
+
1
)
/
2
−
1
)
+
0
(a_n - a_1) + (a_{n - 1} - x) + ... + (a_{(n + 1) / 2 + 1} - a_{(n + 1) / 2 - 1}) + 0
(an−a1)+(an−1−x)+...+(a(n+1)/2+1−a(n+1)/2−1)+0 ,也就是说,上面的式子的值不会小于这个式子。
我们发现,当
x
x
x 取
a
(
n
+
1
)
/
2
a_{(n + 1) / 2}
a(n+1)/2 时与上面的式子的最小值相等,所以此时最小。
n n n 为偶数时
原式
=
(
∣
a
1
−
x
∣
+
∣
a
n
−
x
∣
)
+
(
∣
a
2
−
x
∣
+
∣
a
n
−
1
−
x
∣
)
+
.
.
.
+
(
∣
a
n
/
2
−
x
∣
+
∣
a
n
/
2
+
1
−
x
∣
)
= (|a_1 - x| + |a_n - x|) + (|a_2 - x| + |a_{n - 1} - x|) + ... + (|a_{n / 2} - x| + |a_{n / 2 + 1} - x|)
=(∣a1−x∣+∣an−x∣)+(∣a2−x∣+∣an−1−x∣)+...+(∣an/2−x∣+∣an/2+1−x∣)
上面的式子的最小值为
(
a
n
−
a
1
)
+
(
a
n
−
1
−
x
)
+
.
.
.
+
(
a
n
/
2
+
1
−
a
n
/
2
)
(a_n - a_1) + (a_{n - 1} - x) + ... + (a_{n / 2 + 1} - a_{n / 2})
(an−a1)+(an−1−x)+...+(an/2+1−an/2),也就是说,上面的式子的值不会小于这个式子。
我们发现,当
x
x
x 取
a
n
/
2
a_{n / 2}
an/2 与
a
n
/
2
+
1
a_{n / 2 + 1}
an/2+1 之间时与上面的式子的最小值相等,所以此时最小。
代码实现
在c ++ 中,除法是下取整的,因此 n n n 为奇数时 ( n + 1 ) / 2 = n / 2 + 1 (n + 1) / 2 = n / 2 + 1 (n+1)/2=n/2+1 ,也就是说,在c ++ 中, n n n 为奇数时, x x x 取 n / 2 + 1 n / 2 + 1 n/2+1 时最小,而偶数时取 n / 2 + 1 n / 2 + 1 n/2+1 也是一种最小的情况,所以奇数和偶数可以放在一起求。把 a a a 读入后排序,取 a n / 2 + 1 a_{n / 2 + 1} an/2+1 为 x x x ,求一遍 ∣ a 1 − x ∣ + ∣ a 2 − x ∣ + ∣ a 3 − x ∣ + . . . + ∣ a n − x ∣ |a_1 - x| + |a_2 - x| + |a_3 - x| + ... + |a_n - x| ∣a1−x∣+∣a2−x∣+∣a3−x∣+...+∣an−x∣ 即可。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010;
int n,a[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
int ans = 0;
for(int i = 1; i <= n; i ++ ) ans += abs(a[i] - a[n/2+1]);
printf("%d\n", ans);
return 0;
}
结语
想不出做法时,可以先把答案的式子表示出来,有时问题就能迎刃而解。