1 条题解

  • 0
    @ 2025-11-11 13:12:23

    题目理解

    我们有 nn 个同学,第 ii 个同学在 tit_i 时刻到达车站。摆渡车往返一趟需要 mm 分钟。我们需要安排摆渡车的出发时间,使得所有同学的等车时间之和最小。

    关键规则

    • 摆渡车容量无限
    • 摆渡车回到起点后可以立即出发
    • 等车时间 = 上车时间 - 到达时间(如果为负则取0)

    问题分析

    1. 基本观察

    如果摆渡车在某个时刻 TT 出发,那么:

    • 所有在 TT 之前到达的同学都会在 TT 时刻上车
    • 这些同学的等车时间 = TtiT - t_i(如果 tiTt_i \leq T
    • TT 之后到达的同学需要等待下一班车

    2. 发车间隔的影响

    由于摆渡车往返需要 mm 分钟,如果我们在时刻 TT 发车,那么下一班车的最早发车时间是 T+mT + m

    因此,问题转化为:将时间轴划分为若干区间,每个区间长度为 mm(或更长),每个同学被分配到某个发车时刻,使得总等待时间最小。

    动态规划解法

    1. 状态设计

    dp[i]dp[i] 表示考虑前 ii 个同学(按到达时间排序后的前 ii 个)的最小总等待时间。

    但是这样还不够,因为我们还需要知道最后一班车的发车时间。

    更好的状态设计: dp[i]dp[i] 表示第 ii 个同学是某班车的最后一名乘客时,前 ii 个同学的最小总等待时间。

    2. 状态转移

    对于每个 ii,我们枚举上一班车的最后一名乘客 jj0j<i0 \leq j < i),那么:

    • j+1j+1 到第 ii 个同学乘坐同一班车
    • 这班车的发车时间至少是 max(ti,上一班车返回时间+m)\max(t_i, \text{上一班车返回时间} + m)
    • 具体发车时间可以延迟到某个最优时刻

    更精确的状态转移:

    $$dp[i] = \min_{0 \leq j < i} \left\{ dp[j] + \text{cost}(j+1, i) \right\} $$

    其中 cost(l,r)\text{cost}(l, r) 表示第 ll 到第 rr 个同学乘坐同一班车的最小等待时间之和。

    3. 计算 cost(l, r)

    对于区间 [l,r][l, r] 的同学,如果他们乘坐同一班车:

    • 发车时间必须 tr\geq t_r(最后一个同学到达时间)
    • 为了最小化等待时间,发车时间应该尽可能早,即 T=max(tr,约束条件)T = \max(t_r, \text{约束条件})

    等待时间之和为:

    k=lr(Ttk)\sum_{k=l}^{r} (T - t_k)

    算法优化

    1. 时间离散化

    由于 tit_i 最大可达 4×1064 \times 10^6,直接枚举所有可能时间不可行。但注意到:

    • 发车时间只可能在同学到达时间的基础上稍微延迟
    • 延迟时间不会超过 mm(否则可以提前发车)

    因此,对于每个区间 [l,r][l, r],我们只需要考虑发车时间为 tr+kt_r + k,其中 0k<m0 \leq k < m

    2. 前缀和优化

    计算 k=lr(Ttk)\sum_{k=l}^{r} (T - t_k) 可以优化:

    $$\sum_{k=l}^{r} (T - t_k) = (r-l+1) \cdot T - \sum_{k=l}^{r} t_k $$

    使用前缀和可以在 O(1)O(1) 时间内计算。

    3. 完整的状态转移

    pre[i]pre[i] 为前 ii 个同学到达时间的前缀和,则:

    $$dp[i] = \min_{0 \leq j < i} \left\{ dp[j] + (i-j) \cdot T - (pre[i] - pre[j]) \right\} $$

    其中 T=max(ti,其他约束+k)T = \max(t_i, \text{其他约束} + k)0k<m0 \leq k < m

    关键洞察

    1. 发车时间决策

    对于一班载着 [l,r][l, r] 区间同学的车:

    • 最早发车时间:trt_r
    • 但为了衔接前一班车,可能需要延迟
    • 实际上,发车时间可以取 tr+kt_r + k0k<m0 \leq k < m)中的任意值

    2. 等待时间的计算技巧

    等待时间可以重新表述为:

    $$\text{等待时间} = \text{发车时间} \times \text{人数} - \text{到达时间之和} $$

    这使我们能够使用前缀和快速计算。

    复杂度分析

    • 状态数O(n)O(n)
    • 转移枚举O(n)O(n)
    • 时间选择O(m)O(m)
    • 总复杂度O(n2m)O(n^2 m)

    对于 n500n \leq 500m100m \leq 100,计算量约为 5002×100=25×106500^2 \times 100 = 25 \times 10^6,可以接受。

    边界情况处理

    1. 第一班车:没有前序约束,发车时间就是最后一个同学的到达时间
    2. 空区间j=i1j = i-1 表示第 ii 个同学单独一班车
    3. 时间衔接:确保后一班车不早于前一班车返回时间

    算法步骤总结

    1. 预处理

      • 将同学按到达时间排序
      • 计算到达时间的前缀和数组
    2. 动态规划

      • 初始化 dp[0]=0dp[0] = 0
      • 对于每个 ii,枚举所有可能的 j<ij < i
      • 对于每个 (j,i)(j, i) 对,枚举可能的发车时间偏移 kk
      • 计算该方案下的等待时间,更新 dp[i]dp[i]
    3. 答案提取

      • 答案就是 dp[n]dp[n]

    总结

    这道题的核心在于将复杂的调度问题转化为区间划分问题:

    1. 问题转化:将同学分组,每组乘同一班车
    2. 状态设计:以"某班车的最后一名乘客"作为状态
    3. 等待计算:利用前缀和快速计算区间等待时间
    4. 时间决策:发车时间只需在有限范围内枚举

    通过合理的状态设计和数学优化,我们可以在多项式时间内解决这个看似复杂的调度问题。这种"区间划分 + 前缀和优化"的思路在许多优化问题中都有应用。

    • 1

    信息

    ID
    5234
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    6
    已通过
    1
    上传者