#LC2187. 完成旅途的最少时间 (trips)
完成旅途的最少时间 (trips)
你好,同学。我是你的 OI 金牌教练。今天我们要深入探讨的是一道非常经典、也是 NOI 系列竞赛中出镜率极高的题型——“二分答案”。
这道题 LeetCode 2187 在竞赛界被称为“资源调度”或“任务分配”类问题。它完美体现了如何将一个复杂的“寻找最小值”问题,转化为简单的“可行性判定”问题。
请拿出草稿纸,随我一起拆解。
一、 预备知识点
- 二分答案 (Binary Search on Answer):本题的核心。当答案具有单调性(时间越长,完成的旅途总数越多)时使用。
- 单调性分析:确定函数 (时间 内完成的总次数)是随 递增的。
- 大整数溢出处理 (long long):NOI 竞赛中的易错点。本题的时间范围可达 ,必须使用
long long。 - 计算复杂度理论:理解为什么 比暴力搜索更优。
二、 题目描述 (NOI 风格)
题目名称:完成旅途的最少时间 (trips)
输入文件:trips.in
输出文件:trips.out
【问题描述】
给你一个数组 time ,其中 time[i] 表示第 辆公交车完成一趟旅途所需要的时间。
每辆公交车可以连续完成多趟旅途,即在一趟旅途完成后可以立即开始下一趟旅途。每辆公交车之间互不影响。
同时给你一个整数 totalTrips ,表示所有公交车总共需要完成的旅途数目。
请你计算并输出完成至少 totalTrips 趟旅途所需要的最少时间。
【输入格式】 第一行包含两个正整数 和 ,分别表示公交车的数量和需要完成的总旅途数。 第二行包含 个由空格隔开的正整数,表示每辆车完成一趟旅途的时间。
【输出格式】 输出一个整数,表示完成任务的最少时间。
【样例 1 输入】
3 5
1 2 3
【样例 1 输出】
3
【样例 1 说明】
- :总数 = $\lfloor 1/1 \rfloor + \lfloor 1/2 \rfloor + \lfloor 1/3 \rfloor = 1 + 0 + 0 = 1$
- :总数 = $\lfloor 2/1 \rfloor + \lfloor 2/2 \rfloor + \lfloor 2/3 \rfloor = 2 + 1 + 0 = 3$
- :总数 = $\lfloor 3/1 \rfloor + \lfloor 3/2 \rfloor + \lfloor 3/3 \rfloor = 3 + 1 + 1 = 5$ 最少需要时间 3。
【样例 2 输入】
1 1
2
【样例 2 输出】
2
【数据范围限制】
三、 启发式引导:草稿纸上的推演过程
1. 寻找单调性
请在纸上画一个坐标系:横轴是“花费的时间 ”,纵轴是“能完成的总旅途数 ”。 你会发现:随着 的增加, 绝对不会减少。
- 如果时间 足够完成任务,那么 也一定足够。
- 结论:答案存在明显的单调分界点。
2. 确定二分边界(极其重要)
- 左边界 (Low):1(最少也要 1 单位时间)。
- 右边界 (High):
- 考虑最坏情况:只有一辆车,且它是最慢的那辆(比如 ),要跑 趟。
- 时间可能达到 。所以
High应该设为 或更准确地设为min(time) * totalTrips。
3. 验证函数 (Check)
假设当前二分到的时间是 mid:
- 第 辆车能跑多少趟? 答案是 。
- 将所有车的趟数累加。如果累加和 ,说明
mid时间足够。
四、 算法思路流程图
在 Mermaid 语法中,我们避开特殊字符以确保渲染正确:
graph TD
Start(开始) --> ReadData(读取 n 和 totalTrips)
ReadData --> InitBound(Low = 1, High = 10 的 14 次方)
InitBound --> Loop{Low 小于等于 High}
Loop -- 是 --> CalcMid(Mid = Low + High 的一半)
CalcMid --> CheckFunc(计算 Mid 时间内能完成的总趟数 Sum)
CheckFunc --> Judge{Sum 是否大于等于 totalTrips}
Judge -- 是 --> Record(Ans = Mid, High = Mid - 1)
Judge -- 否 --> MoveLow(Low = Mid + 1)
Record --> Loop
MoveLow --> Loop
Loop -- 否 --> Output(输出 Ans)
Output --> End(结束)
subgraph 验证逻辑
CheckFunc --- C1(遍历 time 数组)
C1 --- C2(Sum 累加 Mid 除以 time-i)
C2 --- C3(注意 Sum 溢出建议提前跳出循环)
end
五、 复杂度分析与优化
1. 时间复杂度分析
- 二分次数: 次。
- Check 函数:每次 。
- 总复杂度:$O(n \log(\text{max\_time} \cdot \text{totalTrips}))$。
- 在 规模下,运算量约 ,远低于 NOI 的 1 秒限制(通常 )。
2. 空间复杂度分析
- 仅需存储
time数组,复杂度 。
3. 优化建议(易错点)
- Long Long:
totalTrips虽然是 ,但Sum的计算过程会远超 ,必须用long long。 - Check 剪枝:在
Sum累加过程中,如果Sum已经大于等于totalTrips,可以立即返回true,防止long long也发生溢出。
六、 总结:读题关键词
在 NOI 赛场上,看到这些词就要联想到“二分答案”:
- “最少时间” / “最大值最小” / “最小值最大”:这是二分答案的最强标志。
- “完成至少 X 个任务”:这定义了单调性的方向。
- “每辆车互不影响”:这意味着总数可以直接相加,判定逻辑简单。
- 数据范围 潜在值:暗示你必须注意数据类型,以及不能使用 的暴力枚举,只能使用 的二分。
同学,思路清晰了吗?现在请在草稿纸上尝试写出 Check 函数的细节,注意处理那几个 long long 的溢出可能。加油!