[蓝桥杯]航班时间

发布于:2025-06-07 ⋅ 阅读:(15) ⋅ 点赞:(0)

航班时间

题目描述

小 h 前往美国参加了蓝桥杯国际赛。小 h 的女朋友发现小 h 上午十点出发,上午十二点到达美国,于是感叹到"现在飞机飞得真快,两小时就能到美国了"。

小 h 对超音速飞行感到十分恐惧。仔细观察后发现飞机的起降时间都是当地时间。由于北京和美国东部有 12 小时时差,故飞机总共需要 14 小时的飞行时间。

不久后小 h 的女朋友去中东交换。小 h 并不知道中东与北京的时差。但是小 h 得到了女朋友来回航班的起降时间。小 h 想知道女朋友的航班飞行时间是多少。

对于一个可能跨时区的航班,给定来回程的起降时间。假设飞机来回飞行时间相同,求飞机的飞行时间。

输入描述

一个输入包含多组数据。

输入第一行为一个正整数 TT,表示输入数据组数。

每组数据包含两行,第一行为去程的 起降 时间,第二行为回程的 起降 时间。

起降时间的格式如下

h1:m1:s1 h2:m2:s2

h1:m1:s1 h3:m3:s3 (+1)

h1:m1:s1 h4:m4:s4 (+2)

表示该航班在当地时间 h1 时 m1 分 s1 秒起飞,

第一种格式表示在当地时间 当日 h2 时 m2 分 s2 秒降落

第二种格式表示在当地时间 次日 h3 时 m3 分 s3 秒降落。

第三种格式表示在当地时间 第三天 h4 时 m4 分 s4 秒降落。

对于此题目中的所有以 h:m:s 形式给出的时间, 保证 ( 0≤h≤23,0≤m,s≤590≤h≤23,0≤m,s≤59).

保证输入时间合法,飞行时间不超过 24 小时。

输出描述

对于每一组数据输出一行一个时间 hh:mm:ss,表示飞行时间为 hh 小时 mm 分 ss 秒。

注意,当时间为一位数时,要补齐前导零。如三小时四分五秒应写 03:04:05。

输入输出样例

示例

输入

3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

输出

04:09:05
12:10:39
14:22:05

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

总通过次数: 3650  |  总提交次数: 3976  |  通过率: 91.8%

难度: 困难   标签: 2018, 字符串, 省赛

算法思路

本题需要计算航班的飞行时间,关键点在于处理时差和跨天情况。核心思路是利用往返飞行时间相等且时差相互抵消的特性:

  1. ​时差抵消原理​​:

    • 设飞行时间为 T,时差为 Δt
    • 去程:起飞时间A + T + Δt = 降落时间B
    • 回程:起飞时间B + T - Δt = 降落时间A
    • 两式相加:2T = (降落B - 起飞A) + (降落A - 起飞B)
  2. ​跨天处理​​:

    • 输入可能包含 (+0)(+1)(+2) 表示当天/次日/第三天降落
    • 将时间统一转换为秒数,并加上跨天的秒数(24小时=86400秒)
  3. ​计算步骤​​:

    • 将起降时间转换为秒数
    • 计算单程时间差(考虑跨天)
    • 往返时间差相加除以2得到飞行时间
    • 将秒数转换为 hh:mm:ss 格式

C++代码实现

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

// 将时间字符串解析为秒数(含跨天处理)
int parseTime(const string& line) {
    // 统一添加(+0)标记
    string s = line;
    if (s.find('(') == string::npos) {
        s += " (+0)";
    }

    int h1, m1, s1, h2, m2, s2, days = 0;
    sscanf(s.c_str(), "%d:%d:%d %d:%d:%d (+%d)", 
           &h1, &m1, &s1, &h2, &m2, &s2, &days);
    
    // 计算起降时间差(秒)
    int start = h1 * 3600 + m1 * 60 + s1;
    int end = h2 * 3600 + m2 * 60 + s2 + days * 86400;
    return end - start;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int T;
    cin >> T;
    cin.ignore(); // 忽略换行符
    
    while (T--) {
        string line1, line2;
        getline(cin, line1);
        getline(cin, line2);
        
        // 计算往返时间差(秒)
        int time1 = parseTime(line1);
        int time2 = parseTime(line2);
        int total = (time1 + time2) / 2;
        
        // 格式化为hh:mm:ss
        int h = total / 3600;
        int m = (total % 3600) / 60;
        int s = total % 60;
        printf("%02d:%02d:%02d\n", h, m, s);
    }
    return 0;
}

代码解析

  1. ​输入处理​​:

    • 使用 getline 读取整行,确保能处理空格和括号
    • 为无标记的行自动添加 (+0)(第10-13行)
  2. ​时间转换​​:

    • parseTime 函数将时间转换为秒数(第9-24行)
    • 计算起降时间差并加上跨天的秒数(第22行)
  3. ​核心计算​​:

    • 往返时间差相加除以2(第34行)
    • 除法使用整数运算避免浮点误差
  4. ​输出格式化​​:

    • printf 确保前导零(第39行)
    • 使用 %02d 保证两位数格式

实例验证

​输入样例​​:

3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

​计算过程​​:

  1. ​第一组​​:

    • 去程:21:57:24 - 17:48:19 = 4h9m5s = 14945s
    • 回程:15:14:23 - 11:05:18 = 4h9m5s = 14945s
    • 飞行时间:(14945+14945)/2 = 14945s = 04:09:05
  2. ​第二组​​:

    • 去程:00:31:46(+1) - 17:21:07 = 7h10m39s = 25839s
    • 回程:16:13:20 - 23:02:41(+1) = 17h10m39s = 61839s
    • 飞行时间:(25839+61839)/2 = 43839s = 12:10:39
  3. ​第三组​​:

    • 去程:20:41:24 - 10:19:19 = 10h22m5s = 37325s
    • 回程:16:41:09 - 22:19:04(+1) = 18h22m5s = 66125s
    • 飞行时间:(37325+66125)/2 = 51725s = 14:22:05

​输出结果​​:

04:09:05
12:10:39
14:22:05

注意事项

  1. ​输入格式处理​​:

    • 必须统一添加 (+0) 标记(第11行)
    • 使用 cin.ignore() 吸收换行符(第28行)
  2. ​时间计算边界​​:

    • 跨天时 end < start 需加24小时(通过 days*86400 处理)
    • 飞行时间不超过24小时(题目保证)
  3. ​输出规范​​:

    • 必须用 %02d 格式化输出
    • 秒数转换时注意取模运算顺序

测试点设计

​测试类型​ ​输入样例​ ​预期输出​ ​验证重点​
当天往返 10:00:00 12:00:00<br>10:00:00 12:00:00 02:00:00 基础计算
跨1天往返 23:00:00 01:00:00 (+1)<br>12:00:00 14:00:00 02:00:00 跨天处理
时差抵消 00:00:00 12:00:00<br>12:00:00 00:00:00 (+1) 12:00:00 时差抵消
极短飞行 00:00:00 00:00:01<br>00:00:00 00:00:01 00:00:01 秒数边界
24小时飞行 00:00:00 00:00:00 (+1)<br>00:00:00 00:00:00 (+1) 24:00:00 最大值

优化建议

  1. ​输入优化​​:

    // 预分配内存减少拷贝
    string line1, line2;
    line1.reserve(30);
    line2.reserve(30);
  2. ​计算优化​​:

    // 位运算替代除法
    int total = (time1 + time2) >> 1;
  3. ​错误处理增强​​:

    // 检查时间合法性
    if (h1 < 0 || h1 > 23 || m1 < 0 || m1 > 59 || ...) {
        cerr << "Invalid time input";
        exit(1);
    }
  4. ​模块化扩展​​:

    struct FlightTime {
        int start, end, days;
        int duration() const { 
            return end - start + days * 86400; 
        }
    };