1. 问题背景与核心需求
这道来自CSP-S 2021的题目"廊桥分配"看似是一个简单的资源调度问题,但深入分析后会发现它巧妙地将堆(优先队列)的应用场景与实际问题相结合。题目描述的是机场廊桥分配的场景:有n架飞机需要停靠,机场有国内和国际两个区域的廊桥,每个区域分配的廊桥数量会影响飞机的停靠效率。我们需要找到最优的廊桥分配方案,使得能够停靠的飞机总数最大化。
在实际机场运营中,廊桥属于高价值资源。一个廊桥在同一时间段只能供一架飞机使用,而远机位(需要摆渡车)的运营成本和时间消耗都显著更高。因此,这道题目具有现实意义——它本质上是在解决"如何用有限资源服务最多需求"的经典优化问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路与算法选择
2.1 暴力解法的局限性
最直观的想法是枚举所有可能的分配方案:将廊桥总数m分成国内和国际两部分(分配i个给国内,m-i个给国际),然后分别计算每种分配下能停靠的飞机总数。这种方法的时间复杂度是O(m*n^2),当n和m较大时(题目中n,m≤1e5),这种解法显然无法在合理时间内完成。
2.2 关键观察与优化思路
这道题的突破口在于认识到:当给某个区域分配k个廊桥时,能够停靠的飞机数量实际上是关于k的非递减函数。也就是说,增加廊桥数量不会减少可停靠的飞机数。基于这个单调性,我们可以:
- 预先计算对于国内/国际区域,分配1-k个廊桥时分别能停靠多少飞机
- 然后枚举所有可能的分配方案i(国内)+j(国际)=m,取最大值
这种预处理的思想将问题分解为两个独立的部分,大大降低了计算复杂度。
2.3 堆(优先队列)的应用场景
计算"给定k个廊桥能停靠多少飞机"的核心在于模拟飞机停靠的过程。这正是堆数据结构的典型应用场景:
- 将飞机按照到达时间排序
- 维护一个最小堆,记录当前可用廊桥的释放时间
- 对于每架飞机,检查是否有廊桥在其到达时已经释放:
- 如果有,复用该廊桥(更新堆)
- 如果没有且还有剩余廊桥,分配新廊桥
- 否则无法停靠
使用堆可以高效地管理廊桥资源,每次操作的时间复杂度是O(log k),整体复杂度为O(n log n)。
3. 详细实现步骤
3.1 数据预处理
cpp复制struct Flight {
int arrive,
