1 条题解

  • 0
    @ 2025-6-16 12:49:26

    解题思路

    1. 解析输入:将输入的各个部分(星期、日期、月份、年份、时间、时区)分别解析并存储
    2. 时区转换
      • 计算原始时区与目标时区(+0300)的差异
      • 调整时间(小时和分钟),处理溢出情况
      • 处理可能导致的日期变更(跨日、跨月、跨年)
    3. 闰年处理:在日期调整时考虑闰年情况
    4. 格式化输出:按照EDATE格式输出转换后的时间

    关键算法实现

    1. 数据结构

    使用mydate结构体存储所有时间信息:

    struct mydate {
        int sec, min, hour;  // 时分秒
        int mday, mon, year, wday; // 日、月、年、星期
        int zone; // 时区偏移(如+0300存储为300)
    };
    

    2. 时区转换核心算法

    void changezone(int zone2) {
        // 计算时区差
        int zonehh = zone/100, zonemm = zone%100;
        int zone2hh = zone2/100, zone2mm = zone2%100;
        
        // 调整时区
        zone = zone2;
        
        // 调整分钟和小时
        if(zone2mm < zonemm) {
            zone2hh--;
            zone2mm += 60;
        }
        hour += zone2hh-zonehh;
        min += zone2mm-zonemm;
        
        // 处理时间溢出
        if(min >= 60) { min %= 60; hour++; }
        if(hour >= 24) { hour -= 24; mday++; wday++; }
        else if(hour < 0) { hour += 24; mday--; wday--; }
        
        // 处理星期溢出
        if(wday >= 7) wday -= 7;
        else if(wday < 0) wday += 7;
        
        // 处理日期溢出(向前)
        if(mday <= 0) {
            --mon;
            if(mon < 0) { mon += 12; --year; }
            bool leap = is_leap(year);
            int thismon = MON_DAY[mon] + (mon == 1 && leap);
            mday += thismon;
        } 
        // 处理日期溢出(向后)
        else {
            bool leap = is_leap(year);
            int thismon = MON_DAY[mon] + (mon == 1 && leap);
            if(mday > thismon) { mday -= thismon; ++mon; }
            if(mon >= 12) { mon -= 12; ++year; }
        }
    }
    

    3. 闰年判断

    bool is_leap(int year) {
        return (year%4==0 && year%100!=0) || (year%400==0);
    }
    

    代码执行流程

    1. 读取并解析输入字符串
    2. 将各部分信息存入mydate结构体
    3. 调用changezone(300)转换为莫斯科时区
    4. 格式化输出转换后的时间

    示例分析

    输入

    SUN, 03 DEC 1996 09:10:35 GMT
    

    处理过程

    1. 解析为:1996年12月3日星期二,09:10:35,时区GMT(+0000)
    2. 转换为+0300时区:
      • 时间增加3小时 → 12:10:35
      • 日期和星期不变
    3. 输出:
    SUN, 03 DEC 1996 12:10:35 +0300
    

    边界情况处理

    1. 跨日转换:如23:00 +0000转换为+0300时变为第二天的02:00
    2. 月末处理:如31日转换后可能变为下月1日
    3. 闰年二月:正确处理28/29天的情况
    4. 年份转换:2位年份自动补全为19XX

    复杂度分析

    • 时间复杂度:O(1) - 所有操作都是常数时间
    • 空间复杂度:O(1) - 使用固定大小的数据结构

    c++实现

    #include <stdio.h>
    #include <stdlib.h>
    #include <cstring>
    #include <iostream>
    using namespace std;
    char WDAY[7][4]  = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
    char MON[12][4]  = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
    char MON_DAY[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    char ZONE[6][4]   = { "UT", "GMT", "EDT", "CDT", "MDT", "PDT" };
    int ZONE_TIME[6] = { 0, 0, -400, -500, -600, -700 };
    struct mydate
    {
        int sec, min, hour;
        int mday, mon, year, wday;
        int zone;
        void changezone(int zone2)
        {
            int zonehh = zone/100, zonemm = zone%100;
            int zone2hh = zone2/100, zone2mm = zone2%100;
            zone = zone2;
            if( zone2mm<zonemm ) zone2hh--, zone2mm+=60;
            hour += zone2hh-zonehh, min += zone2mm-zonemm;
            if( min>=60 ) min%=60, ++hour;
            if( hour>=24 ) ++mday, ++wday, hour-=24;
            else if( hour<0 ) hour+=24, --mday, --wday;
            if( wday>=7 ) wday-=7;
            else if( wday<0 ) wday+=7;
     
            if( mday<=0 )
            {
                --mon;
                if( mon<0 ) mon+=12, --year;
                bool leap = false;
                if( (year%4==0 && year%100!=0) || (year%400==0 ) ) leap = true;
                int thismon = MON_DAY[mon]+(int)(mon==1&&leap);
                mday += thismon;
            }
            else
            {
                bool leap = false;
                if( (year%4==0 && year%100!=0) || (year%400==0 ) ) leap = true;
                int thismon = MON_DAY[mon]+(int)(mon==1&&leap);
                if( mday>thismon ) mday-=thismon, ++mon;
                if( mon>=12 ) mon-=12, ++year;
            }
        }
        void print()
        {
            printf("%s, %02d %s %04d %02d:%02d:%02d %+05d\r\n", WDAY[wday], mday, MON[mon], year, hour, min, sec, zone);
        }
    } xd;
    int main()
    {
        char s[10];
        while( ~scanf("%s", s) )
        {
            s[3] = '\0';
            for(int i=0; i<7; ++i)
                if( !strcmp(s, WDAY[i]) )
                {
                    xd.wday = i;
                    break;
                }
            scanf("%d", &xd.mday);
            scanf("%s", s);
            for(int i=0; i<12; ++i)
                if( !strcmp(s, MON[i]) )
                {
                    xd.mon = i;
                    break;
                }
            scanf("%s", s);
            xd.year = atoi(s);
            if( strlen(s)<=2 ) xd.year+=1900;
            scanf("%2d:%2d:%2d", &xd.hour, &xd.min, &xd.sec);
            scanf("%s", s);
            if( s[0]=='+' || s[0]=='-' )
                sscanf(s, "%d", &xd.zone);
            else
            {
                for(int i=0; i<6; ++i)
                    if( !strcmp(s, ZONE[i]) )
                    {
                        xd.zone = ZONE_TIME[i];
                        break;
                    }
            }
            xd.changezone(300);
            xd.print();
        }
     
        return 0;
    }
    
    • 1

    信息

    ID
    447
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    1
    已通过
    1
    上传者