华为OD机试_2025 B卷_最少面试官数(Python,100分)(附详细解题思路)

题目描述

某公司组织一场公开招聘活动,假设由于人数和场地的限制,每人每次面试的时长不等,并已经安排给定,用(S1,E1)、 (S2,E2)、 (Sj,Ej)…(Si < Ei,均为非负整数)表示每场面试的开始和结束时间。

面试采用一对一的方式,即一名面试官同时只能面试一名应试者,一名面试官完成一次面试后可以立即进行下一场面试,且每个面试官的面试人次不超过 m。

为了支撑招聘活动高效顺利进行,请你计算至少需要多少名面试官。

输入描述
输入的第一行为面试官的最多面试人次 m,第二行为当天总的面试场次 n,

接下来的 n 行为每场面试的起始时间和结束时间,起始时间和结束时间用空格分隔。

其中, 1 <= n, m <= 500

输出描述
输出一个整数,表示至少需要的面试官数量。

用例

输入 2
5
1 2
2 3
3 4
4 5
5 6
输出 3
说明 总共有 5 场面试,且面试时间都不重叠,但每个面试官最多只能面试 2 人次,所以需要 3 名面试官。
输入 3
3
1 2
2 3
3 4
输出 1
说明 总共有3场面试,面试时间不重叠,每个面试官最多能面试3人次,所以只需要一名面试官
输入 3
3
8 35
5 10
1 3
输出 2
说明 总共有3场面试,[5,10]和[8,35]有重叠,所以至少需要2名面试官

面试官调度算法:高效招聘活动的关键

核心解题思路

本题目要求计算在满足面试时间冲突和面试官场次限制的条件下,最少需要多少名面试官。核心思路是分析两个关键约束条件:

  1. 时间冲突约束:同一时间段内进行的面试不能由同一面试官承担
  2. 场次限制约束:每位面试官最多只能进行m场面试

解题步骤

  1. 计算最大并发面试数

    • 使用扫描线算法找出任意时刻同时进行的最大面试数量
    • 这个值决定了所需面试官的最小数量(时间维度)
  2. 计算最小场次需求

    • 基于总面试场次和每人最多m场计算
    • ceil(n/m) 给出满足场次限制的最小面试官数
  3. 综合两个约束

    • 最终需求取上述两个值的最大值
    • 面试官数量 = max(ceil(n/m), max_overlap)

完整代码实现

import math

def main():
    # 读取输入
    m = int(input().strip())  # 每位面试官最多场次
    n = int(input().strip())  # 总面试场次
    intervals = []  # 存储面试时间区间
    
    for i in range(n):
        s, e = map(int, input().split())
        intervals.append((s, e))
    
    # 处理0场面试的特殊情况
    if n == 0:
        print(0)
        return
    
    # 创建事件列表:开始时间+1,结束时间-1
    events = []
    for s, e in intervals:
        events.append((s, 1))
        events.append((e, -1))
    
    # 事件排序:时间相同则先处理结束事件
    events.sort(key=lambda x: (x[0], x[1]))
    
    # 扫描事件计算最大并发数
    current = 0
    max_overlap = 0
    for event in events:
        current += event[1]  # 累加事件值
        if current > max_overlap:
            max_overlap = current
    
    # 计算满足场次限制的最小需求
    min_by_count = math.ceil(n / m)
    
    # 取两个约束的最大值
    result = max(min_by_count, max_overlap)
    print(result)

if __name__ == "__main__":
    main()

算法原理解析

1. 事件扫描算法

events = []
for s, e in intervals:
    events.append((s, 1))   # 面试开始事件
    events.append((e, -1))  # 面试结束事件

events.sort(key=lambda x: (x[0], x[1]))
  • 事件表示
    • 开始事件:(时间点, 1) 表示增加一个面试
    • 结束事件:(时间点, -1) 表示减少一个面试
  • 排序规则
    • 按时间点升序
    • 时间相同则结束事件优先(确保不虚报并发数)

2. 最大并发计算

current = 0
max_overlap = 0
for event in events:
    current += event[1]
    max_overlap = max(max_overlap, current)
  • 扫描过程:按时间顺序处理事件
  • 当前并发current变量记录当前进行中的面试数
  • 峰值更新max_overlap记录整个时间轴上的最大并发值

3. 场次需求计算

min_by_count = math.ceil(n / m)
  • 数学关系:总场次n ÷ 每人最多m场
  • 向上取整:使用math.ceil处理整数约束

4. 综合决策

result = max(min_by_count, max_overlap)
  • 双重约束:满足两者的最大值
  • 充分性证明:这个数量既满足时间冲突要求,又满足场次限制

示例解析

示例1:输入 2(m)、5(n)、时间段(1,2)(2,3)(3,4)(4,5)(5,6)

  1. 事件扫描

    • 事件列表:[(1,1),(2,-1),(2,1),(3,-1),(3,1),(4,-1),(4,1),(5,-1),(5,1),(6,-1)]
    • 排序后:[(1,1),(2,-1),(2,1),(3,-1),(3,1),(4,-1),(4,1),(5,-1),(5,1),(6,-1)]
    • 扫描过程:
      • t=1:current=1, max_overlap=1
      • t=2:先-1(current=0),再+1(current=1)
      • …最大并发始终为1
  2. 场次计算ceil(5/2)=3

  3. 最终结果max(3,1)=3

  4. 输出3

示例2:输入 3(m)、3(n)、时间段(1,2)(2,3)(3,4)

  1. 事件扫描
    • 事件列表:[(1,1),(2,-1),(2,1),(3,-1),(3,1),(4,-1)]
    • 扫描过程:
      • t=1:current=1, max_overlap=1
      • t=2:先-1(current=0),再+1(current=1)
      • …最大并发始终为1
  2. 场次计算ceil(3/3)=1
  3. 最终结果max(1,1)=1
  4. 输出1

示例3:输入 3(m)、3(n)、时间段(8,35)(5,10)(1,3)

  1. 事件扫描
    • 事件列表:[(1,1),(3,-1),(5,1),(8,1),(10,-1),(35,-1)]
    • 排序后:[(1,1),(3,-1),(5,1),(8,1),(10,-1),(35,-1)]
    • 扫描过程:
      • t=1:current=1, max=1
      • t=3:current=0
      • t=5:current=1
      • t=8:current=2, max=2
      • t=10:current=1
      • t=35:current=0
  2. 场次计算ceil(3/3)=1
  3. 最终结果max(1,2)=2
  4. 输出2

总结与扩展

关键知识点

  1. 扫描线算法:高效处理时间区间问题
  2. 事件驱动模型:将时间点抽象为事件
  3. 双重约束处理:时间冲突与资源限制的综合考量
  4. 边界处理:事件排序规则解决同时发生问题

核心启示:扫描线算法是处理时间区间问题的利器,而双重约束分析是资源调度问题的关键。本算法展示了如何将抽象问题转化为可计算的数学模型,并通过高效的事件处理机制得出最优解。

初学者可从中学习:

  1. 问题抽象能力:将实际需求转化为算法模型
  2. 事件驱动思想:时间点作为状态变化触发器
  3. 双重约束分析:平衡资源限制与时间冲突
  4. 算法优化技巧:排序提升扫描效率

你可能感兴趣的:(华为OD机试Python版,华为od,python,开发语言)