华为OD机试_2025 B卷_报文响应时间(Python,100分)(附详细解题思路)
文章目录
- 题目描述
- 核心解题思路
- 关键步骤解析
- 解题步骤详解
- 步骤一:解析最大响应时间字段
- 步骤二:计算每个报文的截止时间
- 步骤三:维护全局最小截止时间
- 完整代码实现
- 总结
题目描述
IGMP 协议中,有一个字段称作最大响应时间 (Max Response Time) ,HOST收到查询报文,解折出 MaxResponsetime 字段后,需要在 (0,MaxResponseTime] 时间 (s) 内选取随机时间回应一个响应报文,如果在随机时间内收到一个新的查询报文,则会根据两者时间的大小,选取小的一方刷新回应时间。
最大响应时间有如下计算方式:
当 Max Resp Code < 128, Max Resp Time = Max Resp Code;
当 Max Resp Code ≥ 128,
Max Resp Time = (mant | 0x10) << (exp + 3);
注: exp最大响应时间的高5~7位: mant 为最大响应时间的低4位。
其中接收到的MaxRespCode 最大值为 255,以上出现所有字段均为无符号数。
现在我们认为 HOST收到查询报文时,选取的随机时间必定为最大值,现给出 HOST 收到查询报文个数 C,HOST 收到该报文的时间T,以及查询报文的最大响应时间字段值 M,请计算出HOST 发送响应报文的时间。
输入描述
第一行为查询报文个数 C,后续每行分别为 HOST 收到报文时间 T,及最大响应时间M,以空格分割。
输出描述
HOST 发送响应报文的时间。
备注
用例确定只会发送一个响应报文, 不存在计时结束后依然收到查询报文的情况。
用例
输入 | 3 0 20 1 10 8 20 |
输出 | 11 |
说明 | 收到3个报文, 第8秒收到第3个报文,响应时间为20秒,则要到8+20=28秒响应,与第上面的报文的响应时间比较获得响应时间最小为11秒; 最终得到最小响应报文时间为11秒 |
输入 | 2 0 255 200 60 |
输出 | 260 |
说明 | 收到2个报文, 第200秒收到第2个报文,响应时间为60秒,则要到200+60-260秒响应,与第上面的报文的响应时间比较获得响应时间最小为260秒: 最终得到最小响应报文时间为260秒 |
核心解题思路
对于这道题,我们需要根据接收到的多个查询报文中的参数,计算出主机发送响应报文的最早时间。每个报文提供的最大响应时间字段决定了该报文对应的响应截止时间。我们需要在这些截止时间中找到最小的一个作为最终结果。
关键步骤解析
-
计算最大响应时间:
- 若字段值
M < 128
,则直接作为最大响应时间。 - 若
M ≥ 128
,需按公式(mant | 0x10) << (exp + 3)
计算。其中exp
是M
的高三位(通过位运算提取),mant
是M
的低四位。
- 若字段值
-
计算截止时间:
- 每个报文的截止时间为接收时间
T
加上对应的最大响应时间。
- 每个报文的截止时间为接收时间
-
维护最小截止时间:
- 遍历所有报文,计算各自的截止时间,并始终保存当前最小的那个。
解题步骤详解
步骤一:解析最大响应时间字段
题目给出的最大响应时间计算分为两种情况:
-
当字段值
M < 128
时
直接取M
作为最大响应时间。例如:M = 20
→ 最大响应时间为 20 秒。
-
当字段值
M ≥ 128
时
需要将M
拆分为高三位exp
和低四位mant
:exp
通过位运算(M & 0xE0) >> 5
提取。mant
通过位运算M & 0x0F
提取。- 代入公式计算:
[
\text{MaxRespTime} = (\text{mant} \mid 0\text{x}10) \ll (\text{exp} + 3)
]
举个例子:
M = 255
(二进制11111111
)时:exp = (255 & 0xE0) >> 5 = 7
mant = 255 & 0x0F = 15
- 计算得
(15 | 0x10) << (7+3) = 31 << 10 = 31744
秒。
步骤二:计算每个报文的截止时间
对于每个报文,其截止时间为接收时间 T
加上对应的最大响应时间:
[
\text{截止时间} = T + \text{MaxRespTime}
]
例如:
- 报文接收时间
T = 0
,M = 255
,则截止时间为0 + 31744 = 31744
秒。
步骤三:维护全局最小截止时间
初始化一个极大值(如 Infinity
),遍历所有报文,计算每个截止时间,并持续更新最小值。最终的最小值即为答案。
示例分析:
- 输入:
2 0 255 200 60
- 处理过程:
- 第一个报文截止时间为
31744
。 - 第二个报文截止时间为
200 + 60 = 260
。 - 最小值更新为
260
,最终输出260
。
- 第一个报文截止时间为
完整代码实现
c = int(input())
min_time = float('inf')for _ in range(c):t, m = map(int, input().split())if m < 128:max_resp = melse:exp = (m & 0xe0) >> 5mant = m & 0x0fmax_resp = (mant | 0x10) << (exp + 3)current_time = t + max_respif current_time < min_time:min_time = current_timeprint(min_time)
总结
本题的关键在于正确处理最大响应时间的计算,并通过遍历维护最小截止时间。位运算的使用是核心技巧,需特别注意 exp
和 mant
的提取方式。最终只需在所有截止时间中取最小值即可得到答案。