题解:AtCoder AT_awc0088_b Bus Tour Group Division

【题目来源】

AtCoder:B - Bus Tour Group Division

【题目描述】

Takahashi is a tour conductor at a travel agency. For the upcoming bus tour, \(N\) participants have signed up, and each participant has a preferred departure time.

The preferred departure time of each participant \(i\) \((1 \leq i \leq N)\) is \(T_i\). According to the travel agency's policy, to operate tours efficiently, participants with similar preferred departure times are grouped together on the same bus. Specifically, for any two participants \(i, j\) on the same bus, the absolute difference of their preferred departure times \(|T_i - T_j|\) must be at most \(K\). There is no upper limit on the number of people that can ride on a single bus.

Takahashi wants to assign every participant to exactly one bus and minimize the number of buses required.

Find the minimum number of buses needed to assign all participants to buses.

高桥是一家旅行社的导游。在即将到来的巴士旅行中,有 \(N\) 名参与者报名,每位参与者都有一个偏好的出发时间。

每位参与者 \(i\)\(1 \leq i \leq N\))的偏好出发时间是 \(T_i\)。根据旅行社的政策,为了高效运营旅行,偏好出发时间相近的参与者会被分到同一辆巴士上。具体来说,对于同一辆巴士上的任意两位参与者 \(i, j\),他们偏好出发时间的绝对差 \(|T_i - T_j|\) 必须不超过 \(K\)。一辆巴士可以乘坐的人数没有上限。

高桥希望将每位参与者分配到恰好一辆巴士上,并最小化所需巴士的数量。

求将所有参与者分配到巴士上所需的最少巴士数量。

【输入】

\(N\) \(K\)
\(T_1\) \(T_2\) \(\ldots\) \(T_N\)

  • The first line contains \(N\), the number of participants, and \(K\), the maximum allowed absolute difference in preferred departure times for participants on the same bus, separated by a space.
  • The second line contains the preferred departure times \(T_1, T_2, \ldots, T_N\) of each participant, separated by spaces.

【输出】

Print the minimum number of buses needed to assign all participants to buses, on a single line.

【输入样例】

5 3
1 5 3 9 12

【输出样例】

3

【核心思想】

  1. 问题分析:给定 \(N\) 个参与者的偏好出发时间 \(T_1, T_2, \ldots, T_N\),要求将所有人分成若干组(每辆巴士一组),使得同一组内任意两人的时间差不超过 \(K\)。目标是使分组数量最少。这是一个排序 + 贪心分组问题,关键在于利用排序后的单调性,每次尽可能多地装入同一辆巴士。

  2. 算法选择

    • 排序:将 \(T_i\) 按升序排列,使同一组内的元素在数组中连续
    • 贪心策略:每辆巴士从当前最小未分配时间开始,尽可能装入后续满足差值约束的参与者
  3. 关键步骤

    • 初始化:读取 \(N\)(参与者数量)和 \(K\)(最大允许时间差)
    • 读取并排序
      • 读取数组 \(T[1..N]\)
      • sort(T + 1, T + N + 1):升序排序
    • 贪心分组
      • 初始化 ans = 1(至少一辆巴士),last = T_1(当前巴士最早出发时间)
      • 遍历 \(i\)\(2\)\(N\)
        • T_i - last \leq K:当前参与者与当前巴士最早出发时间差不超过 \(K\),可以同乘,继续
        • 否则:ans++(新开一辆巴士),last = T_i(以当前时间为新巴士的最早出发时间)
    • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \log N)\),排序 \(O(N \log N)\),贪心遍历 \(O(N)\)
    • 空间复杂度:\(O(N)\),存储时间数组 \(T[1..N]\)
  5. 排序后贪心的核心思想

    • 排序降维:将无序的时间点排序后,同一巴士内的参与者必然在数组中形成连续区间,将二维配对问题转化为一维区间覆盖问题
    • 贪心最优性:每辆巴士从当前最早未分配时间开始,尽可能向右延伸,这是最优策略。若跳过某个可分配的参与者将其放入下一辆巴士,不会减少总巴士数
    • 差值约束转化:排序后只需比较当前元素与组首元素的差,无需两两比较,将 \(O(M^2)\) 的组内判断降为 \(O(1)\)
    • 最少分组等价:问题等价于"用长度不超过 \(K\) 的区间覆盖所有点,求最少区间数",贪心策略(每次区间尽可能向右延伸)是该经典问题的最优解
    • 适用于"分组约束为元素间最大差值"的最少分组问题,排序后贪心可保证最优

【算法标签】

其他排序

【代码详解】

#include <bits/stdc++.h>
using namespace std;

// 定义数组最大容量
const int N = 200005;

// 全局变量声明
int n, k;       // n: 元素个数, k: 允许的最大差值
int a[N];       // 存储所有元素的数组

// 主函数入口
int main()
{
    // 读取元素个数n和差值限制k
    cin >> n >> k;

    // 循环读取n个元素到数组中
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    // 对数组进行升序排序
    sort(a + 1, a + n + 1);

    // 贪心算法:计算最少需要多少个分组
    int ans = 1;        // 至少有一个分组
    int last = a[1];    // 记录当前分组的第一个元素

    // 从第二个元素开始遍历
    for (int i = 2; i <= n; i++)
    {
        // 如果当前元素与分组起始元素的差值不超过k,则归入同一组
        if (a[i] - last <= k)
            continue;
        else
        {
            // 否则开启新分组,更新分组起始元素
            ans++;
            last = a[i];
        }
    }

    // 输出最少分组数量
    cout << ans << endl;

    return 0;
}

【运行结果】

5 3
1 5 3 9 12
3
posted @ 2026-07-04 09:37  团爸讲算法  阅读(4)  评论(0)    收藏  举报