华为OD-100-响应报文时间(C C++ Java Py JS)

题目描述

IGMP 协议中,有一个字段称作最大响应时间 (MaxResponseTime) ,HOST 收到查询报文,解折出 MaxResponsetime 字段后,需要在 (0,MaxResponseTime] 时间 (s) 内选取随机时间回应一个响应报文,如果在随机时间内收到一个新的查询报文,则会根据两者时间的大小,选取小的一方刷新回应时间。

最大响应时间有如下计算方式:

  • MaxRespCode < 128, MaxRespTime = MaxRespCode
  • MaxRespCode128, MaxRespTime = (mant | 0x10) << (exp + 3);

在这里插入图片描述
注: exp 最大响应时间的高 5~7 位,mant 为最大响应时间的低 4 位。

其中接收到的 MaxRespCode 最大值为 255,以上出现所有字段均为无符号数。

现在我们认为 HOST 收到查询报文时,选取的随机时间必定为最大值,现给出 HOST 收到查询报文个数 CHOST 收到该报文的时间 T,以及查询报文的最大响应时间字段值 M,请计算出 HOST 发送响应报文的时间。

输入描述

第一行为查询报文个数 C,后续每行分别为 HOST 收到报文时间 T,及最大响应时间 M,以空格分割。

输出描述

HOST 发送响应报文的时间。

备注

用例确定只会发送一个响应报文, 不存在计时结束后依然收到查询报文的情况。

示例1

输入

3
0 20
1 10
8 20

输出

11

说明

收到3个报文,

  • 第0秒收到第1个报文,响应时间为20秒,则要到0+20=20秒响应;
  • 第1秒收到第2个报文,响应时间为10秒,则要到1+10=11秒响应,与上面的报文的响应时间比较获得响应时间最小为11秒;
  • 第8秒收到第3个报文,响应时间为20秒,则要到8+20=28秒响应,与第上面的报文的响应时间比较获得响应时间最小为11秒;

最终得到最小响应报文时间为11秒

解析

本题考查逻辑模拟、位运算。

假设

  • 在第 t1 秒收到第 1 个查询报文,最大响应时间为 m1,即最迟在第 t1 + m1 秒发送响应报文。
  • 在第 t2 秒收到第 2 个查询报文,最大响应时间为 m2,即最迟在第 t2 + m2 秒发送响应报文。
  • 在第 tc 秒收到第 c 个查询报文,最大响应时间为 mc,即最迟在第 tc + mc 秒发送响应报文。

最后,我们需要选择 min(t1+m1,t2+m2,…,tc+mc) 时刻做发送响应报文的时间。

需要注意的是,本题收到的查询报文的最大响应时间 m

  • 若 m < 128,则 m 可以直接当成最大响应时间
  • 若 m ≥ 128,则需要取出 m 的二进制形式下的高 3~5 位作为 mant,低 4 位作为 exp,代入公式:(mant | 0x10) >> (exp + 3) ,公式结果为最大响应时间

那么如何取出 m 二进制形式下的高 3 ~ 5 位,以及低 4 位呢?

这里可以使用 “按位与&” 运算,按位与运算的特点是:进行计算的两个二进制数的对应位值都为1时,结果对应位的值才为1,否则为0。

比如:任何数 x 和二进制数 0000 1111 进行按位与的结果都是 x 二进制形式下低 4 位二进制的结果

01010111
&00001111
00000111

同理,任何数 x 和二进制数 0111 0000 进行按位与的结果都是 x 二进制形式下高 3 ~ 5 位保留,其余位为0,如下图

01010111
&01110000
01010000

由于本题需要保留高 3 ~ 5 位为新的二进制数,因此上面按位与结果二进制,还需要右移4位

0101 0000 >> 4 的结果位 0000 0101

源码实现

C

#include <stdio.h>
#include <limits.h>
#include <math.h>

int main() {
    int c;
    scanf("%d", &c);

    int result = INT_MAX;

    for (int i = 0; i < c; i++) {
        int t, m;
        scanf("%d %d", &t, &m);

        if (m >= 128) {
            int mant = m & 0b00001111;
            int exp = (m & 0b01110000) >> 4;
            m = (mant | 0x10) << (exp + 3);
        }

        result = (int) fmin(result, t + m);
    }

    printf("%d", result);

    return 0;
}

C++

#include <bits/stdc++.h>

using namespace std;

int main() {
    int c;
    cin >> c;

    int result = INT_MAX;

    for (int i = 0; i < c; i++) {
        int t, m;
        cin >> t >> m;

        if (m >= 128) {
            int mant = m & 0b00001111;
            int exp = (m & 0b01110000) >> 4;
            m = (mant | 0x10) << (exp + 3);
        }

        result = min(result, t + m);
    }

    cout << result;

    return 0;
}

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int c = sc.nextInt();

        int result = Integer.MAX_VALUE;

        for (int i = 0; i < c; i++) {
            int t = sc.nextInt();
            int m = sc.nextInt();

            if (m >= 128) {
                int mant = m & 0b00001111;
                int exp = (m & 0b01110000) >> 4;
                m = (mant | 0x10) << (exp + 3);
            }

            result = Math.min(result, t + m);
        }

        System.out.println(result);
    }
}

Python

if __name__ == '__main__':
    c = int(input())

    result = float('inf')

    for _ in range(c):
        t, m = map(int, input().split())

        if m >= 128:
            mant = m & 0b00001111
            exp = (m & 0b01110000) >> 4
            m = (mant | 0x10) << (exp + 3)

        result = min(result, t + m)

    print(result)

JavaScript

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  const c = parseInt(await readline());

  let result = Number.MAX_VALUE;

  for (let i = 0; i < c; i++) {
    let [t, m] = (await readline()).split(" ").map(Number);

    if (m >= 128) {
      const mant = m & 0b00001111;
      const exp = (m & 0b01110000) >> 4;
      m = (mant | 0x10) << (exp + 3);
    }

    result = Math.min(result, t + m);
  }

  console.log(result);
})();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码到自然成

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值