廊桥分配(CSP-S-2021-T1)通俗题解

本文介绍了廊桥分配问题,探讨了如何最大化停靠廊桥的飞机数量。通过两种方案,包括朴素的贪心算法和找规律优化,分析了飞机停靠廊桥的策略。文章以蓝桥杯比赛题目为背景,提供了输入输出样例和代码实现,讨论了时间复杂度并分享了优化后的算法思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

题目描述

输入输出样例

 题解:

方案一(朴素):

方案二(找规律优化):

Code(优化):

Code(不要喷我^_O_^)(35)(后面还有)

Code(55)(我也服了我自己) 

Gift For you


题目描述

当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。

机场分为国内区和国际区,国内航班飞机只能停靠在国内区,国际航班飞机只能停靠在国际区。一部分廊桥属于国内区,其余的廊桥属于国际区。

L 市新建了一座机场,一共有 n 个廊桥。该机场决定,廊桥的使用遵循“先到先得”的原则,即每架飞机抵达后,如果相应的区(国内/国际)还有空闲的廊桥,就停靠在廊桥,否则停靠在远机位(假设远机位的数量充足)。该机场只有一条跑道,因此不存在两架飞机同时抵达的情况。

现给定未来一段时间飞机的抵达、离开时刻,请你负责将 n 个廊桥分配给国内区和国际区,使停靠廊桥的飞机数量最多。

输入格式

输入的第一行,包含三个正整数 n,m1​,m2​,分别表示廊桥的个数、国内航班飞机的数量、国际航班飞机的数量。

接下来m1​ 行,是国内航班的信息,第 i 行包含两个正整数 a1,i​,b1,i​,分别表示一架国内航班飞机的抵达、离开时刻。

接下来m2​ 行,是国际航班的信息,第 i 行包含两个正整数a2,i​,b2,i​,分别表示一架国际航班飞机的抵达、离开时刻。

每行的多个整数由空格分隔。

输出格式

输出一个正整数,表示能够停靠廊桥的飞机数量的最大值。

输入输出样例

输入 #1复制

3 5 4
1 5
3 8
6 10
9 14
13 18
2 11
4 15
7 17
12 16

输出 #1复制

7

输入 #2复制

2 4 6
20 30
40 50
21 22
41 42
1 19
2 18
3 4
5 6
7 8
9 10

输出 #2复制

4

输入 #3复制

见附件中的 airport/airport3.in

输出 #3复制

见附件中的 airport/airport3.ans

说明/提示

【样例解释 #1】

在图中,我们用抵达、离开时刻的数对来代表一架飞机,如 (1,5) 表示时刻 1 抵达、时刻 5 离开的飞机;用 √ 表示该飞机停靠在廊桥,用 × 表示该飞机停靠在远机位。

我们以表格中阴影部分的计算方式为例,说明该表的含义。在这一部分中,国际区有 22 个廊桥,44 架国际航班飞机依如下次序抵达:

  1. 首先 (2, 11) 在时刻 2 抵达,停靠在廊桥。
  2. 然后 (4, 15) 在时刻 4 抵达,停靠在另一个廊桥。
  3. 接着 (7, 17)在时刻 7 抵达,这时前 22 架飞机都还没离开、都还占用着廊桥,而国际区只有 22 个廊桥,所以只能停靠远机位。
  4. 最后 (12, 16)在时刻 12 抵达,这时 (2, 11) 这架飞机已经离开,所以有 1 个空闲的廊桥,该飞机可以停靠在廊桥。

根据表格中的计算结果,当国内区分配 2 个廊桥、国际区分配 1 个廊桥时,停靠廊桥的飞机数量最多,一共 7架。

【样例解释 #2】

当国内区分配 2 个廊桥、国际区分配 0 个廊桥时,停靠廊桥的飞机数量最多,一共 4 架,即所有的国内航班飞机都能停靠在廊桥。

需要注意的是,本题中廊桥的使用遵循“先到先得”的原则,如果国际区只有 1 个廊桥,那么将被飞机 (1,19) 占用,而不会被 (3,4)、(5,6)、(7,8)、(9,10) 这 4 架飞机先后使用。

 题解:

设飞机降落的时间为 Start, 离开廊桥的时间为 Leave

首先要设定两个数组,分别记录国内和国外航班。考虑到题目要求是飞机先到先得,那么自然而然就想到,要按Start的大小递增排序。因为STL中的set容器有自动排列顺序的功能,我们可以这样来保存数据:

1. 定义一个结构体plane,保存Start和Leave

struct plane{
	int start;
	int leave;
};

2.定义一个plane类型的容器line,保存廊桥内停靠的飞机。

另外定义两个plane类型的容器inside,outside,分别表示国内国外飞机依次来临的顺序

另外为了访问set中的元素,同时为plane类型定义一个迭代器(指针)

set <plane> line;
set <plane> inside;
set <plane> outside;
set <plane>::iterator it;
廊桥分配问题是指给定一座长度为n的廊桥以及m个人,每个人需要跨过廊桥到对面。廊桥每次只能让两个人同时通过,且只有两个人的速度加和不超过廊桥长度时才能通过。每个人过桥所需的时间不同,要求找到一种过桥方案使得所有人的总过桥时间最短。 该问题可以通过使用线段树的解法。首先,将n个位置看作是一棵树,每个节点对应一个位置。然后,我们将所有人按照过桥时间从小到大排序,并按照排序结果为每个节点分配一个排序编号。接下来,从左到右遍历排序后的人员列表,对于每个人,我们找到其对应的节点,并为该节点分配一个值,表示该位置可以被占用。 这样,在分配完所有人的节点后,我们得到了一个线段树,每个非叶子节点表示一个廊桥位置,叶子节点表示一个人,其父节点的值表示桥上人员的速度加和。通过遍历这颗树,可以计算出所有人过桥的最短总时间。 具体操作如下: 1. 根据所有人的过桥时间从小到大排序。 2. 为每个节点分配排序编号。 3. 初始化线段树的所有节点为空(未占用)。 4. 从左到右遍历排序后的人员列表,对于每个人: a. 找到对应的节点。 b. 判断该节点是否为空,如果为空,表示该位置可以被占用,否则找到该节点的兄弟节点(该节点的父节点的其他子节点)。 c. 将该节点或其兄弟节点标记为占用,并更新父节点的值。 5. 遍历线段树,计算所有人过桥的总时间。 使用线段树解决廊桥分配问题的时间复杂度为O(nlogn),因为排序的时间复杂度为O(nlogn),遍历人员列表的时间复杂度为O(n),遍历线段树的时间复杂度为O(nlogn)。总的空间复杂度为O(n)
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

感谢有你陪伴

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值