题解:学而思编程 货仓选址

【题目来源】

学而思编程:货仓选址

【题目描述】

在一条数轴上有 \(n\) 家商店,它们的坐标分别为 \(a_1\)\(a_n\)

现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。

为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

【输入】

第一行输入整数 \(n\)

第二行 \(n\) 个整数 \(a_1\)\(a_n\)

【输出】

输出一个整数,表示距离之和的最小值。

【输入样例】

4
6 2 9 1

【输出样例】

12

【核心思想】

  1. 问题分析:给定 \(n\) 个商店在数轴上的坐标 \(a_1, a_2, \ldots, a_n\),需要选择一个位置建立货仓,使得货仓到所有商店的距离之和最小。这是一个经典的中位数贪心问题,关键在于最优位置是中位数。

  2. 算法选择

    • 中位数性质:对于一维数轴上的点,使得到所有点距离之和最小的位置是中位数
    • 数学证明:设选址位置为 \(x\),总距离为 \(f(x) = \sum_{i=1}^{n} |a_i - x|\)。当 \(x\) 为中位数时,\(f(x)\) 取得最小值
    • 配对优化:排序后,最大与最小配对、次大与次小配对,每对的差值之和即为答案
  3. 关键步骤

    • 读取输入\(n\)(商店数量)、\(a[1..n]\)(商店坐标)
    • 排序sort(a + 1, a + n + 1) 从小到大排序
    • 配对计算(遍历 \(i\)\(1\)\((n+1)/2\)):
      • 配对差值ans += a[n-i+1] - a[i](最大与最小配对)
    • 输出结果:最小距离之和 \(ans\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n \log n)\),主要是排序复杂度
    • 空间复杂度:\(O(n)\),存储商店坐标
  5. 中位数贪心的核心思想

    • 中位数最优性:在一维情况下,中位数是使得到所有点距离之和最小的位置
    • 排序配对技巧:排序后首尾配对,利用对称性简化计算
    • 贪心正确性:中位数将数轴分成两部分,左右两侧的点数平衡,总距离最小
    • 数学推导:通过绝对值函数的性质可以严格证明中位数的最优性
    • 适用于一维选址问题、距离最小化、带权中位数等问题

【算法标签】

贪心

【代码详解】

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long n, a[100005], ans;  // ans: 最终结果

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);  // 从小到大排序

    // 计算最大元素与最小元素的差值之和
    for (int i = 1; i <= (n + 1) / 2; i++)
    {
        ans += a[n - i + 1] - a[i];  // 最大与最小配对
    }
    cout << ans;
    return 0;
}

【运行结果】

4
6 2 9 1
12
posted @ 2026-06-14 10:47  团爸讲算法  阅读(9)  评论(0)    收藏  举报