当前位置:   article > 正文

日期&&时差&&星期问题(蓝桥杯)_蓝桥杯时间算法

蓝桥杯时间算法

目录

1、常见时间、日期类问题思路

2、核心模板 ——判断日期是否合法

3、日期问题&&回文日期

4、日期差值、星期几

5、航班时间


1、常见时间、日期类问题思路

  • 日期问题、回文日期——(题目给定两个时间点,让找到之间满足条件的日期有多少个)

     思路:用一个循环直接枚举,先判断是否是正常的日期,再判断是否满足条件。

  • 日期差值、星期几——(题目给定两个日期,让我们求中间相差多少天)

      思路:用数学计算出每个日期距离0001年01月01日有多少天,然后相减即可。

  • 航班时间——(给定两个飞机的起飞时间和抵达时间,求在天上飞了多少时间。**各地区存在时差**)

      思路:经过化简时差可以约掉((t1-时差)-(t2-时差))/2=(t1+t2)/2,最后转化成秒进行相加再/2就行了。

  • 有坑有大坑!!!在后台的隐藏数据,两个日期可能是颠倒的,并不一定是前面是小日期,后面是大日期。如果题目上没有明确给出第一个日期小,第二个日期大,那就必定有坑,就需要我们用max判断一下,再进行计算。

2、核心模板 ——判断日期是否合法

  1. int check(int year, int month, int day)//判断是否为合法的日期
  2. {
  3. if (month == 0 || month > 12) return 0;
  4. if (day == 0) return 0;
  5. if (month != 2)
  6. {
  7. if (day > days[month]) return 0;
  8. }
  9. if(month==2)
  10. {
  11. int lsp = year % 400 == 0 || year % 4 == 0 && year % 100 != 0;
  12. if (day > 28 + lsp) return 0;
  13. }
  14. return 1;
  15. }

3、日期问题&&回文日期

题目描述——日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。

小明知道这些日期都在1960年1月1日至2059年12月31日。

令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。

更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入格式
一个日期,格式是”AA/BB/CC”。

即每个’/’隔开的部分由两个 0-9 之间的数字(不一定相同)组成。

输出格式
输出若干个不相同的日期,每个日期一行,格式是”yyyy-MM-dd”。

多个日期按从早到晚排列。

数据范围
0≤A,B,C≤9


输入样例:
 

02/03/04


输出样例:
 

  1. 2002-03-04
  2. 2004-02-03
  3. 2004-03-02
  1. #include<iostream>//日期问题
  2. #include<algorithm>
  3. using namespace std;
  4. int a, b, c;
  5. int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
  6. int check(int year, int month, int day)
  7. {
  8. if (month == 0 || month > 12) return 0;
  9. if (day == 0) return 0;
  10. if (month != 2)
  11. {
  12. if (day > days[month]) return 0;
  13. }
  14. if(month==2)
  15. {
  16. int lsp = year % 400 == 0 || year % 4 == 0 && year % 100 != 0;
  17. if (day > 28 + lsp) return 0;
  18. }
  19. return 1;
  20. }
  21. int main()
  22. {
  23. scanf("%d/%d/%d", &a, &b, &c);//巧妙借用scanf的输入格式
  24. for (int i = 19600101; i <= 20591231; i++)
  25. {
  26. int year = i / 10000;
  27. int month = i % 10000 / 100;
  28. int day = i % 100;
  29. if (check(year, month, day))
  30. {
  31. if (year%100 == a && month == b && day == c //年月日
  32. || year%100 == c && month == a && day == b //月日年
  33. || year%100 == c && month == b && day == a) //日月年
  34. {
  35. printf("%d-%02d-%02d\n", year, month, day);
  36. }
  37. }
  38. }
  39. return 0;
  40. }

题目描述——回文日期

在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用 8 位数字表示一个日期,其中,前 4 位代表年份,接下来 2 位代表月份,最后 2 位代表日期。

显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的 8 位数字是回文的。

现在,牛牛想知道:在他指定的两个日期之间(包含这两个日期本身),有多少个真实存在的日期是回文的。

一个 8 位数字是回文的,当且仅当对于所有的 i(1≤i≤8) 从左向右数的第 i 个数字和第 9−i 个数字(即从右向左数的第 i 个数字)是相同的。

例如:

对于 2016 年 11 月 19 日,用 8 位数字 20161119 表示,它不是回文的。
对于 2010 年 1 月 2 日,用 8 位数字 20100102 表示,它是回文的。
对于 2010 年 10 月 2 日,用 8 位数字 20101002 表示,它不是回文的。


输入格式
输入包括两行,每行包括一个 8 位数字。

第一行表示牛牛指定的起始日期 date1,第二行表示牛牛指定的终止日期 date2。保证 date1 和 date2 都是真实存在的日期,且年份部分一定为 4 位数字,且首位数字不为 0。

保证 date1 一定不晚于 date2。

输出格式
输出共一行,包含一个整数,表示在 date1 和 date2 之间,有多少个日期是回文的。

输入样例:
 

  1. 20110101
  2. 20111231


输出样例:
 

1
  1. #include<iostream>//回文日期
  2. #include<algorithm>
  3. using namespace std;
  4. int x, y, ans;
  5. int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
  6. int check(int year, int month, int day)
  7. {
  8. if (month == 0 || month > 12) return 0;
  9. if (day == 0) return 0;
  10. if (month != 2)
  11. {
  12. if (day > days[month]) return 0;
  13. }
  14. if (month == 2)
  15. {
  16. int lsp = year % 400 == 0 || year % 4 == 0 && year % 100 != 0;
  17. if (day > 28 + lsp) return 0;
  18. }
  19. return 1;
  20. }
  21. int main()
  22. {
  23. ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
  24. cin >> x >> y;
  25. for (int i = x; i <= y; i++)
  26. {
  27. int year = i / 10000;
  28. int month = i % 10000 / 100;
  29. int day = i % 100;
  30. if (check(year, month, day))
  31. {
  32. if (year / 1000 == day % 10 && year / 100 % 10 == day / 10 && year / 10 % 10 == month % 10 && year % 10 == month / 10)
  33. {
  34. ans++;
  35. }
  36. }
  37. }
  38. cout << ans << endl;
  39. return 0;
  40. }

4、日期差值、星期几

题目描述——日期差值

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

输入格式
输入包含多组测试数据。

每组数据占两行,分别表示两个日期,形式为 YYYYMMDD。

输出格式
每组数据输出一行,即日期差值。

数据范围
年份范围 [1,9999],
保证输入日期合法。

输入样例:
 

  1. 20110412
  2. 20110422


输出样例:
 

11
  1. #include<iostream>//一直有个别数据相差1,给我整emo了......
  2. #include<algorithm>//最后发现虽然考虑闰年了,但考虑的条件少了一部分!!!啊啊啊啊啊
  3. using namespace std;
  4. int n, m;
  5. int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
  6. int cal(int n)
  7. {
  8. int ans=0;
  9. int year = n / 10000;
  10. int month = n % 10000 / 100;
  11. int day = n % 100;
  12. for (int i = 1; i < year; i++)
  13. {
  14. if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0) ans++;
  15. }
  16. ans += (year - 1) * 365;
  17. for (int i = 1; i < month; i++)
  18. {
  19. ans += days[i];
  20. }
  21. if(year%400==0&&month>2||year%4==0&&year%100!=0&&month>2) ans++;//*********就错在这
  22. ans += day;
  23. return ans;
  24. }
  25. int main()
  26. {
  27. ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
  28. while (cin >> n >> m)
  29. {
  30. if (n < m) swap(n, m);
  31. cout << cal(n) - cal(m) + 1 << endl;
  32. }
  33. return 0;
  34. }

题目描述——星期几

已知 1 年 1 月 1 日是星期一。现在给定一个日期,请你判断是星期几。

注意闰年的 2 月有 29 天。

满足下面条件之一的是闰年:

  • 年份是 4 的整数倍,而且不是 100 的整数倍;
  • 年份是 400 的整数倍。

输入格式
输入包含多组测试数据。

每组数据占一行,包含一个整数 d 表示日,一个字符串 m 表示月,一个整数 y 表示年。

月份 1∼12,依次如下所示:

January, February, March, April, May, June, July, August, September, October, November, December


输出格式
每组数据输出一行结果,输出一个字符串表示给定日期是星期几。

周一至周日依次如下所示:

Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday


数据范围
1000≤y≤3000,
给定日期保证合法。
每个输入最多包含 100 组数据。

输入样例:
 

  1. 9 October 2001
  2. 14 October 2001


输出样例:
 

  1. Tuesday
  2. Sunday
  1. #include<iostream>//星期几
  2. #include<algorithm>
  3. using namespace std;
  4. typedef long long LL;
  5. LL sum;
  6. int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
  7. string weeks[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
  8. string months[13] = { "0","January","February","March","April","May","June","July","August","September","October","November","December" };
  9. int main()
  10. {
  11. LL n, m, x;
  12. string str;
  13. ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
  14. while (cin >> m >> str >> n)
  15. {
  16. int year = n;
  17. int month;
  18. int day = m;
  19. for (int i = 1; i <= 12; i++)
  20. {
  21. if (str == months[i]) month = i;
  22. }
  23. sum = (year - 1) * 365;//求(year-1)年有多少天
  24. for (int i = 1; i < year; i++)
  25. {
  26. if (i % 400 == 0 || i % 4 == 0 && i % 100 != 0) sum++;//求(year-1)年有多少闰年
  27. }
  28. for (int i = 1; i < month; i++)
  29. {
  30. sum += days[i];//求year年有多少天
  31. }
  32. sum += day;
  33. if (year % 400 == 0 && month > 2 || year % 4 == 0 && year % 100 != 0 && month > 2)
  34. {
  35. sum++;//判断year年是否是闰年
  36. }
  37. cout << weeks[sum % 7] << endl;
  38. }
  39. return 0;
  40. }

5、航班时间

题目描述——航班时间

小 h 前往美国参加了蓝桥杯国际赛。

小 h 的女朋友发现小 h 上午十点出发,上午十二点到达美国,于是感叹到“现在飞机飞得真快,两小时就能到美国了”。小 h 对超音速飞行感到十分恐惧。

仔细观察后发现飞机的起降时间都是当地时间。

由于北京和美国东部有 12 小时时差,故飞机总共需要 14 小时的飞行时间。

不久后小 h 的女朋友去中东交换。小 h 并不知道中东与北京的时差。

但是小 h 得到了女朋友来回航班的起降时间。小 h 想知道女朋友的航班飞行时间是多少。

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

输入格式
一个输入包含多组数据。

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

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

起降时间的格式如下:

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秒降落。

第二种格式表示该航班在当地时间h1时m1分s1秒起飞,在当地时间次日h2时m2分s2秒降落。

第三种格式表示该航班在当地时间h1时m1分s1秒起飞,在当地时间第三日h2时m2分s2秒降落。

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

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

数据范围
保证输入时间合法(0≤h≤23,0≤m,s≤59),飞行时间不超过24小时。

输入样例:

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


输出样例:
 

  1. 04:09:05
  2. 12:10:39
  3. 14:22:05

  1. //去乘起飞时间+航行时间+时差=去乘降落时间 (公式一)
  2. //回程起飞时间+航行时间-时差=回程降落时间 (公式二)
  3. //根据公式一+公式二:
  4. //去乘起飞时间+回程起飞时间+2*航行时间=去乘降落时间+回程降落时间
  5. //航行时间=(去乘降落时间-去乘起飞时间+回程降落时间-回程起飞时间)/2
  6. #include<iostream>//航班时差
  7. #include<algorithm>
  8. using namespace std;
  9. int get_time()
  10. {
  11. int h1, h2, m1, m2, s1, s2, d = 0, sum;
  12. scanf("%d:%d:%d %d:%d:%d (+%d)", &h1, &m1, &s1, &h2, &m2, &s2, &d);
  13. sum = (d * 24 * 3600 + h2 * 3600 + m2 * 60 + s2) - (h1 * 3600 + m1 * 60 + s1);
  14. return sum;
  15. }
  16. int main()
  17. {
  18. int n;
  19. cin >> n;
  20. for (int i = 1; i <= n; i++)
  21. {
  22. int t1 = get_time();
  23. int t2 = get_time();
  24. int t = (t1 + t2) / 2;
  25. printf("%02d:%02d:%02d\n", t / 3600, t / 60 % 60, t % 60);
  26. }
  27. return 0;
  28. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/870273
推荐阅读
相关标签
  

闽ICP备14008679号