通过率 45% · 提交 1,944 · 通过 873
小慕负责筹备一场大型文艺汇演,园区内同时有多场演出在进行。由于每场演出都只能完整观看,不能中途入场或提前离场,而且小慕一次只能观看一场演出。此外,不同演出分布在园区的不同场地,因此连续两场观看之间至少需要留出 15 分钟的时间用于转场。 小慕是个狂热的文艺爱好者,希望能尽可能多地观看演出。 现在给定演出的时间安排表,请你帮小慕计算出他最多能观看多少场演出。
这类题属于华为 OD 机考真题方向中「200分 / LIS问题」方向的高频题型,通常考察对「200分 / LIS问题」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
第一行为一个数 N,表示演出场数,1 <= N <= 1000。
接下来 N 行,每行两个空格分割的整数,第一个整数 T 表示演出的开始时间,第二个整数 L 表示演出的持续时间,T 和 L 的单位为分钟,0 <= T <= 1440, 0 < L <= 100。
最多能观看的演出场数。
示例 1
输入示例
2 720 120 840 120
输出示例
1
第一场演出开始时间是第720分钟,经过120分钟演出结束,即第840分钟结束,此时还需要15分钟的间隔时间,即要等到第855分钟才可以看下一场演出,故来不及看第二场在第840分钟开始的演出。最多只能看1场演出。
示例 2
输入示例
2 20 60 100 60
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
相关图解步骤
先看指定步骤补关键知识点,再回到本题完成标准输入输出。
注意,本题和 无重叠区间 几乎完全一致。
我们可以储存每一场演出的开始和结束时间,即按照 [start, end] 的方式进行储存,储存在列表 intervals 中。由于题目要求 每间隔 15 分钟 才能够看下一场演出,所以我们可以把每一场演出的结束时间再加上 15 分钟,这样题目就转变为:考虑所有不重叠的 `[start, end]` 区间的最大数目。处理输入的代码如下:
为了方便我们贪心地思考问题,我们先按照 开始时间 `start` 从小到大对间隔列表 intervals 进行排序。
然后我们考虑相邻的两场演出,[start1, end1] 和 [start2, end2],由于 intervals 已经排序,必然存在 start1 <= start2 成立,故这两场演出之间的关系存只有以下三种可能性:
1. `start1 < end1 <= start2 < end2`,即演出 2 的开始时间在演出 1 的结束时间之后。故看完演出 1,可以继续看演出 2。 2. `start1 <= start2 <= end1 <= end2`,即演出 2 的开始时间在演出 1 的结束时间之前,但演出 2 的结束时间在演出 1 的结束时间之后。故看完演出 1 之后,没办法观看演出 2。而且 选择演出 1 进行观看是更划算的,因为它结束得更早,预留出更多的时间去观看后续的演出。 3. `start1 <= start2 <= end2 <= end1`,即演出 2 的开始时间和结束时间均在演出 1 的结束时间之前。故看完演出 1 之后,没办法观看演出 2。为了尽可能多地看更多的演出,在选择观看的演出时,我们会 直接选择演出 2 而不是演出 1(即使演出 1 的开始时间更早),因为演出 2 的结束时间更早,有充裕的时间去观看后续的演出。
理解了相邻两场演出的三种可能性之后,我们发现解决问题的关键实际上在于考虑 演出 1 的结束时间 `end1` 和 演出 2 的间隔 `[start2, end2]` 之间的关系:
end1 在 [start2, end2] 之前end1 在 [start2, end2] 之间end1 在 [start2, end2] 之后由于我们需要遍历排序后的间隔列表 intervals 中的每一个间隔 [start, end]。因此可以维护变量 `pre_end`,表示上一场演出的结束时间。初始化 pre_end = -inf,表示第一场演出始终可以观看。
考虑当前间隔 [start, end] 和上一场演出结束时间 pre_end 之间的关系,我们可以得到以下逻辑:
[start, end] 进行观看(对应情况 1)。能观看的演出场次 ans += 1。由于选择了 [start, end] 进行观看,下一场演出的观看时间应该由当前的 end 决定,即对于下一场演出而言,当前结束时间 end 是上一场演出的结束时间,故更新 pre_end = end。[start, end] 进行观看(对应情况 2)。由于 pre_end ≤ end,因此我们保留之前的 pre_end,作为判断下一场演出是否能观看的依据。故无需做任何事情。[start, end] 来代替上一场演出 [pre_start, pre_end](对应情况 3)。由于 pre_end > end,选择 end 作为判断下一场演出是否能观看的依据是更佳的选择,即我们不去选择观看 pre_end 所对应的之前某场演出,而选择观看当前的演出 [start, end],这样的选择有利于后面留出充裕的时间来尽可能地观看更多演出,故更新 pre_end = end。整理上述逻辑后,代码为:
实际上,当我们对间隔列表 intervals 排序之后,我们也可以把这个问题当作经典的 LIS 问题(最长递增子序列)进行处理。
譬如对于上述例子,我们所选的演出应该为演出 1、4、5。换句话说,我们需要找到尽可能多的演出区间,所有演出区间均需要满足 start ≥ pre_end,其中 start 为第 i 个区间的开始时间,pre_end 为上一个区间即第 i-1 个区间的结束时间。这是一个非常自然的 LIS 问题,故也可以用 dp 来解决问题。
我们考虑动态规划三部曲:
dp 数组是一个长度为 n 的一维列表,dp[i] 表示 包含了第 `i` 场演出 `intervals[i]` 的最长无重叠演出数目。
包含了第 i 场演出 intervals[i] 的最长无重叠演出数目,由前面的 i-1 场演出中(用索引 j 表示),结束时间 intervals[j][1] 小于当前演出开始时间 intervals[i][0] 且 dp[j] 最大的那场演出决定。
包含第 1 场演出的最长无重叠演出数目为 1。 dp[0] = 1
解法一:贪心
复杂度分析
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
输出示例
2
第一场演出开始时间是第20分钟,经过60分钟演出结束,即第80分钟结束,此时还需要15分钟的间隔时间,即要等到第95分钟才可以看下一场演出,第二场演出在第100分钟开始的演出,赶得上观看第二场演出。最多可以观看2场演出。
示例 3
输入示例
4 10 20 100 20 150 60 80 40
输出示例
3
时间限制 1000 ms · 内存限制 128 MB
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有