通过率 35% · 提交 900 · 通过 311
小慕在赤道上均匀部署了N个信号塔,按位置顺序编号为0~N-1。 1、初始状态下所有的信号塔都是未激活状态; 2、信号塔的激活方式分为“手动激活”和“关联激活”两种方式; 3、如果在时刻1一个信号塔被激活,下一个时刻2与之相邻的两个信号塔就会被“关联激活”; 4、如果准备激活某个信号塔时,它已经被激活了,则什么都不用做; 5、信号塔0与信号塔N-1是相邻的; 小慕计划挑选某些信号塔在某些时刻进行“手动激活”,当然最终所有的信号塔都会被激活。 哪些信号塔最晚被激活呢?
这类题属于华为 OD 机考真题方向中「100分 / 2024E」方向的高频题型,通常考察对「100分 / 2024E」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
第一行两个数字N和E,中间有空格
N代表部署发动机的总个数,E代表计划手动启动的发动机总个数1<N<=1000,1<=E<=1000,E<=N
接下来共E行,每行都是两个数字T和P,中间有空格
T代表发动机的手动启动时刻,P代表此发动机的位置编号。0<=T<=N,0<=P<=N
第一行一个数字N,以回车结束N代表最后被启动的发动机个数
第二行N个数字,中间有空格,以回车结束每个数字代表发动机的位置编号,从小到大排序
示例 1
输入示例
8 2 0 1 1 7
输出示例
2 4 5
示例 2
输入示例
8 2 0 2 0 6
输出示例
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
相关图解步骤
先看指定步骤补关键知识点,再回到本题完成标准输入输出。
考虑示例二的过程,可以看到最后被启动的发动机是 4 和 5。
首先我们可以比较快速地定位出这是一个 BFS 问题。 因为上一时刻启动的发动机,会使得其相邻的其他未启动发动机在下一个时刻启动。 这有点类似于 病毒感染 或者 波纹传播 等模型。
主要要解决两个问题:
1. 这是一个 1 维环型数组,和我们经常遇到的二维网格模型有所不同。 2. 本题还存在 时间先后 的概念,某些发动机在中间的某些时刻会被 手动启动(而不都是在最开始被启动)。
把上述两个问题处理好,加以我们常用的 BFS 解题套路,本题其实不算难题。
---
常规的二维网格 DFS/BFS,在考虑近邻位置的时候,我们是取 上下左右 四个方向。 对于一维数组某一个元素的近邻位置,我们只需要考虑 左右 两个方向。
特别地,由于需要处理 环型数组,我们在位置 0 和位置 N-1 需要进行额外判断。 可以构建函数 get_neighbor() 进行分类讨论,来获得元素 x 的两个近邻位置,即:
或者使用 取余 的写法,即:
---
另一个更加重要的问题是 延时处理 的问题。 由于同一个时刻启动的发动机可能不止一台,我们首先使用 哈希表 来储存所有手动启动的发动机的信息。
哈希表 table 中储存了所有手动启动的发动机信息。 其中 key 为若干的启动时刻 T,value 为在同一个 T 中启动的若干发动机 P 构成的列表。
例如对于例子:
构建的哈希表为:
我们知道,在 BFS 过程中的元素出队意味着我们要考虑其近邻元素的情况。 如果是不考虑延时入队的普通情况,我们会这样来完成 BFS 过程:
特别注意,total 表示的是发动机的 启动总数量。 在单层搜索下(同一个时刻的搜索),队列 q 中的所有元素都是在当前时刻要启动的发动机编号。 所以在当前时刻,total 增加的量为 qSize = len(q)。
为了找到 最后一次启动 的那些机器,我们可以多设置一个条件用来判断。 一旦发现 total 增加后数量为 N,说明在这个时刻中队列 q 中的所有元素,就是最后启动的发动机编号,也就是答案。因此我们可以看到代码中存在:
其中 ans 就是最终要输出的答案。
---
现在我们把 延时入队 的事情考虑进来。 在 BFS 过程中,我们可以设置一个变量 cur_time,来表示当前进行到的时刻。 在进行到某一个时刻的时候,如果发现 cur_time 位于 table 中,意味着存在若干发动机是在这个时刻被 手动启动 的。这些发动机需要被加入到队列 q 中。即:
这部分代码必须加在 更新 `total` 之前。 另外,每次 while 循环结束后,cur_time 还需要递增 1,表示整体的时刻增加。因此 BFS 过程的整体代码为:
复杂度分析 设信号塔个数为 N,手动激活信息条数为 E。读入并构建哈希表 table 为 O(E),取所有手动激活时刻的最小值也是 O(E)。BFS 主体中,check_list 保证每个信号塔至多入队一次,出队时只考察环上左右两个邻居,出入队的总代价为 O(N);每条手动激活信息也只在对应时刻被处理一次,共 O(E)。需要注意外层 while 是按时刻逐轮推进的(cur_time 从最小手动激活时刻开始每轮加一),若手动激活时刻之间有空档,中间轮次只做常数工作,因此循环轮数取决于最晚有效激活时刻与 N 的量级。最后对最晚激活的塔编号排序,设其数量为 K(K 不超过 N),代价 O(K log K)。综合起来时间复杂度为 O(N + E + K log K) 再加上时刻推进的轮数;空间上 check_list 为 O(N),哈希表为 O(E),队列至多 O(N),即 O(N + E)。
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
2 0 4
时间限制 1000 ms · 内存限制 128 MB
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有