1 条题解

  • 0
    @ 2025-12-9 16:57:11

    标准题解代码 (NOIP C++14)

    /**
     * 题目:环球飞行 (Global Flight)
     * 难度:GESP 4级 / CSP-J 普及-
     * 知识点:模拟、模运算、时间换算
     */
    
    #include <iostream>
    #include <cstdio> // 用于 printf 格式化输出
    
    using namespace std;
    
    int main() {
        // 提升 cin 速度
        ios::sync_with_stdio(false);
        cin.tie(NULL);
    
        int N, Z_curr, H, M;
        if (!(cin >> N >> Z_curr >> H >> M)) return 0;
    
        // 核心思路:将所有时间转化为相对于【第0天 00:00】的【总分钟数】
        // 使用 long long 防止溢出(虽然本题数据范围 int 足够,但这是好习惯)
        // 初始总分钟数 = 小时*60 + 分钟
        long long total_minutes = (long long)H * 60 + M;
    
        // 循环处理 N 段航程
        for (int i = 0; i < N; ++i) {
            int h_fly, m_fly, z_next;
            cin >> h_fly >> m_fly >> z_next;
    
            // 1. 加上物理飞行时间
            total_minutes += (h_fly * 60 + m_fly);
    
            // 2. 加上时差影响
            // 时差 = 新时区 - 旧时区
            // 例如从 +8 到 -5: (-5) - 8 = -13 小时,即时间要倒退 13 小时
            int time_diff = z_next - Z_curr;
            total_minutes += time_diff * 60;
    
            // 更新当前所在时区
            Z_curr = z_next;
        }
    
        // 计算最终结果
        const int MINUTES_PER_DAY = 24 * 60; // 1440 分钟
    
        // 1. 计算天数 Day
        // 难点:处理负数。例如 -100 分钟,应该是 Day -1 的 22:20。
        // C++ 中整数除法 -100 / 1440 = 0,但这不符合日期的逻辑(我们需要向下取整)
        long long day;
        if (total_minutes >= 0) {
            day = total_minutes / MINUTES_PER_DAY;
        } else {
            // 对于负数,如果能整除(如 -1440),就是 Day -1
            // 如果不能整除(如 -100),也是 Day -1
            // 通用向下取整公式: floor(a/b)
            // 手写逻辑:
            if (total_minutes % MINUTES_PER_DAY == 0) {
                day = total_minutes / MINUTES_PER_DAY;
            } else {
                day = total_minutes / MINUTES_PER_DAY - 1;
            }
        }
    
        // 2. 计算当天的小时和分钟
        // 难点:处理负数取模。C++ 中 -100 % 1440 = -100。
        // 我们需要的是正的时刻。公式:((a % b) + b) % b
        int minute_of_day = (total_minutes % MINUTES_PER_DAY + MINUTES_PER_DAY) % MINUTES_PER_DAY;
        
        int final_h = minute_of_day / 60;
        int final_m = minute_of_day % 60;
    
        // 输出,注意补前导0
        printf("Day %lld %02d:%02d\n", day, final_h, final_m);
    
        return 0;
    }
    

    数据生成器 (Data Generator)

    这是配套的测试数据生成器,修正了样例数据的逻辑,并覆盖了跨天、负数日期等边界情况。

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <cstdio>
    
    using namespace std;
    
    // 解决逻辑
    void solve(int N, int Z_curr, int H, int M, const vector<vector<int>>& flights, ofstream& fout) {
        long long total = (long long)H * 60 + M;
        
        for(const auto& f : flights) {
            int h_fly = f[0];
            int m_fly = f[1];
            int z_next = f[2];
            
            total += (h_fly * 60 + m_fly);
            total += (z_next - Z_curr) * 60;
            Z_curr = z_next;
        }
        
        const int DAY_MIN = 1440;
        long long day;
        if(total >= 0) day = total / DAY_MIN;
        else {
            if(total % DAY_MIN == 0) day = total / DAY_MIN;
            else day = total / DAY_MIN - 1;
        }
        
        int m_day = (total % DAY_MIN + DAY_MIN) % DAY_MIN;
        int fh = m_day / 60;
        int fm = m_day % 60;
        
        // 手动格式化输出到文件
        fout << "Day " << day << " ";
        if(fh < 10) fout << "0";
        fout << fh << ":";
        if(fm < 10) fout << "0";
        fout << fm << endl;
    }
    
    int main() {
        // 构造 10 个测试点
        for(int i = 1; i <= 10; ++i) {
            string in_name = to_string(i) + ".in";
            string out_name = to_string(i) + ".out";
            ofstream fin(in_name);
            ofstream fout(out_name);
            
            int N, Z0, H0, M0;
            vector<vector<int>> flights;
            
            // 生成数据策略
            if (i == 1) { // 样例1
                N=2; Z0=8; H0=9; M0=30;
                flights = {{12,0,-5}, {3,30,8}};
            } else if (i == 2) { // 样例2
                N=1; Z0=0; H0=23; M0=0;
                flights = {{2,0,-1}};
            } else if (i == 3) { // 负数日期测试:往西飞,倒时差
                N=2; Z0=0; H0=1; M0=0; 
                // 1:00起飞,飞1小时,去-5区 -> 1+1-5 = -3:00 -> Day -1 21:00
                flights = {{1,0,-5}, {0,0,-5}};
            } else if (i == 4) { // 跨多天测试
                N=5; Z0=0; H0=0; M0=0;
                // 每次飞20小时
                for(int k=0; k<5; k++) flights.push_back({20, 0, 0});
            } else {
                // 随机数据
                N = rand() % 10 + 1;
                Z0 = rand() % 24 - 11;
                H0 = rand() % 24;
                M0 = rand() % 60;
                int z_prev = Z0;
                for(int k=0; k<N; k++) {
                    int hf = rand() % 15;
                    int mf = rand() % 60;
                    int zn = rand() % 24 - 11;
                    flights.push_back({hf, mf, zn});
                }
            }
            
            // 写入输入
            fin << N << " " << Z0 << " " << H0 << " " << M0 << endl;
            for(auto& f : flights) {
                fin << f[0] << " " << f[1] << " " << f[2] << endl;
            }
            
            // 写入输出
            solve(N, Z0, H0, M0, flights, fout);
            
            fin.close();
            fout.close();
            cout << "Generated Case " << i << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    19274
    时间
    1000ms
    内存
    32MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者