POJ 1446 - Moscow Time - 模拟

题目大意:

输入年、月、日、星期、小时、分钟、秒,以及所处的时区,要求将其转换成UTC+3时区内的时间。

浑身都是坑的模拟题。

①题目没有说是单组还是多组数据(其他OJ上的版本是多组数据),保险起见建议处理到EOF。

②"Year: Set by two or four decimal digits. If a year is set by two decimals it is assumed that this is a number of the year of the XX century."

我查了谷歌翻译才反应过来那个XX是罗马数字20……输入年份时不能直接"%d",得先读成字符串,再判断长度,如果长度为2则在转成整数时需要加上1900。

③"First two digits set the hours and the last two the minutes of offset value."

在求该时区与UTC+3相差的偏移量时,不能简单粗暴地用300减去读入的数。假如输入+0130,那么300-130的结果就是170,该结果显然是错误的。

④"The absolute value of the difference does not exceed 24 hours."

注意-2350这样的极端情形,加的天数有可能是2天!(虽然现实中不存在-2350这样的时区划分,但本题的数据就不好说了)

⑤"Your program should rely on the predefined correctness of the given Day-of-week and Time-zone."

这句话的意思其实是说输入数据保证格式和内容都是正确的,我一开始看到这句还愣了一会儿(没见过这种操作)……

⑥"February, as a rule, has 28 days, save for the case of the leap year (29 days)."

学到了一个新短语:save for(手动笑哭

本题是需要考虑闰年的,闰年的判定法与现实一致:四年一闰,百年不闰,四百年再闰。

⑦"The output string should not include leading and trailing spaces."

注意行末不能有空格。另外输出时一定要注意加前导零。

AC代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <stdexcept>
  5 #include <string>
  6 
  7 const char dayOfWeekName[7][4] = {
  8         "SUN",
  9         "MON",
 10         "TUE",
 11         "WED",
 12         "THU",
 13         "FRI",
 14         "SAT"
 15 };
 16 const char monthName[12][4] = {
 17         "JAN",
 18         "FEB",
 19         "MAR",
 20         "APR",
 21         "MAY",
 22         "JUN",
 23         "JUL",
 24         "AUG",
 25         "SEP",
 26         "OCT",
 27         "NOV",
 28         "DEC"
 29 };
 30 const char timeZoneOffsetName[6][4] = {
 31         "UT",
 32         "GMT",
 33         "EDT",
 34         "CDT",
 35         "MDT",
 36         "PDT"
 37 };
 38 const int timeZoneOffset[6] = {0, 0, -400, -500, -600, -700};
 39 const int dayNumberOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //non-leap year
 40 
 41 inline bool isLeapYear(int year)
 42 {
 43     return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
 44 }
 45 
 46 inline int getMonthId(const char* month)
 47 {
 48     for (int i = 0; i < 12; i++)
 49         if (strcmp(month, monthName[i]) == 0)
 50             return i;
 51 
 52     throw std::invalid_argument("invalid month name: " + std::string(month));
 53 }
 54 
 55 inline int getDayOfWeekId(const char* dayOfWeek)
 56 {
 57     for (int i = 0; i < 7; i++)
 58         if (strcmp(dayOfWeek, dayOfWeekName[i]) == 0)
 59             return i;
 60 
 61     throw std::invalid_argument("invalid day of week: " + std::string(dayOfWeek));
 62 }
 63 
 64 int getOffset(const char* timeZone)
 65 {
 66     if (timeZone[0] == '+' || timeZone[0] == '-') //in digit form
 67         //return 300 - atoi(timeZone); //WRONG!!!
 68     {
 69         int tz = atoi(timeZone); //example: +0235
 70         if (tz > 0 && tz < 300)
 71             tz += 40; //+0235 -> 275
 72         return 300 - tz; //+0235 -> 275 -> +0025
 73     }
 74     else
 75         for (int i = 0; i < 6; i++)
 76             if (strcmp(timeZone, timeZoneOffsetName[i]) == 0)
 77                 return 300 - timeZoneOffset[i];
 78 
 79     throw std::invalid_argument("invalid time zone: " + std::string(timeZone));
 80 }
 81 
 82 int advanceClock(int& hour, int& minute, int offset)
 83 {
 84     if (offset >= 0)
 85     {
 86         minute += offset % 100;
 87         if (minute >= 60)
 88         {
 89             minute -= 60;
 90             hour += 1;
 91         }
 92         hour += offset / 100;
 93         if (hour >= 24)
 94         {
 95             int temp = hour / 24;
 96             hour %= 24;
 97             return temp;
 98         }
 99     }
100     else //offset < 0
101     {
102         minute -= (-offset % 100);
103         if (minute < 0)
104         {
105             minute += 60;
106             hour -= 1;
107         }
108         hour -= (-offset / 100);
109         if (hour < 0)
110         {
111             hour += 24;
112             return -1;
113         }
114     }
115     return 0;
116 }
117 
118 void forwardDate(int& year, char* month, int& dayOfMonth, char* dayOfWeek, int offset)
119 {
120     int monthId = getMonthId(month); //0-based
121     int curDayNumber = dayNumberOfMonth[monthId] + (monthId == 1 && isLeapYear(year));
122 
123     int dayOfWeekId = getDayOfWeekId(dayOfWeek);
124     strcpy(dayOfWeek, dayOfWeekName[(dayOfWeekId + 1) % 7]);
125 
126     if ((dayOfMonth += offset) > curDayNumber)
127     {
128         dayOfMonth = 1;
129         if ((monthId += 1) >= 12)
130         {
131             monthId = 0;
132             year += 1;
133         }
134     }
135     strcpy(month, monthName[monthId]); //maybe advanced before
136 }
137 
138 void backwardDate(int& year, char* month, int& dayOfMonth, char* dayOfWeek)
139 {
140     int monthId = getMonthId(month); //0-based
141 
142     int dayOfWeekId = getDayOfWeekId(dayOfWeek);
143     strcpy(dayOfWeek, dayOfWeekName[(dayOfWeekId + 6) % 7]);
144 
145     if ((dayOfMonth -= 1) <= 0)
146     {
147         if ((monthId -= 1) < 0)
148         {
149             monthId = 11;
150             year -= 1;
151         }
152         dayOfMonth = dayNumberOfMonth[monthId] + (monthId == 1 && isLeapYear(year));
153         //update dayOfMonth before monthId
154     }
155     strcpy(month, monthName[monthId]);
156 }
157 
158 bool solve()
159 {
160     char dayOfWeek[5];
161     char month[4];
162     char timeZone[8];
163     char yearStr[5];
164     int dayOfMonth;
165     int year;
166     int hour, minute, second;
167     int offset;
168 
169     if (scanf("%s%d%s%s%d:%d:%d%s", dayOfWeek, &dayOfMonth, month, yearStr,
170               &hour, &minute, &second, timeZone) == EOF)
171         return false;
172 
173     dayOfWeek[3] = '\0'; //erase the comma
174     year = (strlen(yearStr) == 4 ? atoi(yearStr) : 1900 + atoi(yearStr));
175 
176     offset = getOffset(timeZone);
177     int advanceClockResult = advanceClock(hour, minute, offset);
178 
179     if (advanceClockResult >= 1)
180         forwardDate(year, month, dayOfMonth, dayOfWeek, advanceClockResult);
181     else if (advanceClockResult == -1)
182         backwardDate(year, month, dayOfMonth, dayOfWeek);
183 
184     printf("%s, %02d %s %04d %02d:%02d:%02d +0300",
185            dayOfWeek, dayOfMonth, month, year, hour, minute, second);
186 
187     return true;
188 }
189 
190 int main()
191 {
192     for (int i = 0; solve(); i++)
193     {
194         if (i > 0)
195             putchar('\n');
196     }
197     return 0;
198 }

 

posted @ 2018-02-22 20:13  Onlynagesha  阅读(339)  评论(0编辑  收藏  举报