【日期】车辆限行
2012年4月1日,北京是人民政府根据《中华人民共和国道路交通安全法》和《北京市实施〈中华人民共和国大气污染防 治法〉办法》有关规定,自2012年4月11日起,继续对机动车实施按车牌尾号工作日高峰时段 区域限行交通管理措施。
根据规定,按车牌尾号限行的机动车车牌尾号分为五组,每13周轮换一次限行日,分别为:
(1) 自2012年4月9日至2012年7月7日:3和8、4和9、5和0、1和6、2和7
(2) 自2012年7月8日至2012年10月6日:2和7、3和8、4和9、5和0、1和6
(3) 自2012年10月7日至2013年1月5日:1和6、2和7、3和8、4和9、5和0
(4) 自2013年1月6日至2013年4月10日:5和0、1和6、2和7、3和8、4和9
(星期一到星期五)
现给出 2012 年 4 月 9 日之后的任意日期,如果不考虑国家统一的公假,只考虑日期一个因素,请计算指定日期要限行的车牌尾号。
(政府的公告确实有点意思,在时间衔接上和限号安排上公告(http://unn.people.com.cn/GB/14748/17574443.html)与公告(http://www.gov.cn/gzdt/2013-04/02/content_2367908.htm)之间有重叠,显然,后面的公告是覆盖前面的公告的,我们计算的时候,只能是“理论”上的事情,咱严格按照从 2012年4月9日 星期一 开始,每 13 周进行一次轮换计算就可以了。)
样例:
序号 | 测试输入 | 期待的输出 | 额外进程 |
---|---|---|---|
1 | 2012 7 9↵ | 2 and 7.↵ | 0 |
2 | 2012 7 12↵ | 5 and 0.↵ | 0 |
3 | 2012 7 14↵ | Free.↵ | 0 |
4 | 2013 4 11↵ | 2 and 7.↵ | 0 |
5 | 2014 4 4 | 5 and 0.↵ | 0 |
思路
首先观察规律(我用1表示 1 and 6,以此类推)
3 4 5 1 2
2 3 4 5 1
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
3 4 5 1 2
2 3 4 5 1
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
...
很明显每五轮循环一次,那每个循环内呢?以向右偏移为正方向
3 4 5 1 2 第0轮 offset = 0
2 3 4 5 1 第1轮 offset = 1
1 2 3 4 5 第2轮 offset = 2
5 1 2 3 4 第3轮 offset = 3
4 5 1 2 3 第4轮 offset = 4
3 4 5 1 2 第5轮 offset = 0
2 3 4 5 1 第6轮 offset = 1
1 2 3 4 5 第7轮 offset = 2
5 1 2 3 4 第8轮 offset = 3
4 5 1 2 3 第9轮 offset = 4
...
发现规律了吗?是的,偏移量刚好是周数模5!
那么我们就发现规律了:
只要先算出所求日期到2012-04-09的星期数,除以13(向下取整)得到轮换次数,再偏移对应偏移量即可(要注意周六周日的情况,以及偏移后大于5怎么办)
代码
#include <stdio.h>
int a[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
char x[6][9] = { "0","3 and 8.","4 and 9.", "5 and 0.", "1 and 6.", "2 and 7."};
int allday(int y, int m, int d)
{
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) a[2] = 29;
int add = d;
y--;
for (int i = 1; i < m; i++) add += a[i];
int day = y*365 + y / 4 - y / 100 + y / 400 + add;
return day;
}
int main()
{
int y, m, d,ad,day,wd;
scanf("%d %d %d", &y, &m, &d);
ad = allday(y, m, d);
day = ad - 734602;
wd = ad % 7;
if (1 <= wd && wd <= 5)
{
wd -= day / 7 / 13;
while (wd < 1) wd += 5;
printf("%s\n", x[wd]);
}
else
printf("Free.\n");
}