1、题目+代码+小结
- 【codeup1928】日期差值(地址:http://codeup.cn/contest.php?cid=100000578)
题目描述
有两个日期,求两个日期间天数,若两日期连续,则规定它们之间天数为两天。
输入格式
两个日期(两行),形式为YYYYMMDD。
输出格式
输出一行,即日期差值。
对平年闰年的处理:可通过二维数组int month[12][2]来存放每个月的天数。
思路1:
分别算出0000/01/01至题目输入日期的总天数,再算出绝对值。代码如下:
#include<cstdio>
int month[12][2]={{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
bool isLeap(int year)
{
return (year%4==0 && (year%100!=0 || year%400==0));
}
int leapCount(int y)//统计[0,y]之间的闰年个数
{
return (y/4-y/100+y/400);
}
int getDays(int y,int m,int d) //计算[0000/01/01,y/m/d]的天数
{
int amount=0;
amount += y*365 + leapCount(y-1)*1; // 计算[0,y-1]年之间的天数
if(isLeap(y))
{
for(int i=0;i<m-1;i++)
{
amount+=month[i][1];
}
}
else
{
for(int i=0;i<m-1;i++)
{
amount+=month[i][0];
}
}
//printf("year+month amount:%d\n",amount);
amount+=d;
return amount;
}
int main()
{
int t1,y1,m1,d1;
int t2,y2,m2,d2;
scanf("%d%d",&t1,&t2);
if(t1<t2) //简化计算,假设第一日期早于第二日期,否则交换
{
int temp=t1;
t1=t2;
t2=temp;
}
y1 = t1/10000;
y2 = t2/10000;
m1 = t1/100-y1*100;
m2 = t2/100-y2*100;
d1 = t1-y1*10000-m1*100;
d2 = t2-y2*10000-m2*100;
//printf("%d%d%d",y1,m1,d1);
int amount1,amount2,ans;
amount1 = getDays(y1,m1,d1);
amount2 = getDays(y2,m2,d2);
ans = amount1-amount2+1;
printf("%d",ans);
return 0;
}
思路2:
令当前日期为早的那个日期,使用循环不断令天数+1,直到等于晚点那个日期,可统计出答案。进一步简化为:
首先年份不断+1至相差一;
其次月份不断+1至相差一;
最后算日期。
代码如下(未简化):
注:
将月份数组写为:
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
//month[m][isLeap(y)] 即为该月份的日期 m:1-12
#include<cstdio>
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
bool isLeap(int year)
{
return (year%4==0 && (year%100!=0 || year%400==0));
}
int main()
{
int t1,y1,m1,d1;
int t2,y2,m2,d2;
int ans=0;
scanf("%d%d",&t1,&t2);
if(t1>t2)
{
int temp=t1;
t1=t2;
t2=temp;
}
y1 = t1/10000;
y2 = t2/10000;
m1 = t1/100-y1*100;
m2 = t2/100-y2*100;
d1 = t1-y1*10000-m1*100;
d2 = t2-y2*10000-m2*100;
while(y1!=y2||m1!=m2||d1!=d2)
{
ans++;
if(d1==month[m1][isLeap(y1)])//判断是否月末
{
d1=1;
if(m1==12)//判断是否为12月
{
y1++;
m1=1;
}
else
{
m1++;
}
}
else
{
d1++;
}
}
printf("%d",ans);
return 0;
}
总结
1、将年月日转化为相对天数处理;
2、对闰年平年的处理,可使用二维数组:
int month[13][2]=int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
或
int month[12][2]=int month[13][2]={{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
推荐第一种,使用时下标与月份一致;
3、若使用思路二的简化方法,注意年份、月份不能加至相等,避免出现2019.4 2020.1,相差不足一年。代码如下:
#include<cstdio>
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
bool isLeap(int year)
{
return (year%4==0 && (year%100!=0 || year%400==0));
}
int main()
{
int t1,y1,m1,d1;
int t2,y2,m2,d2;
int ans=0;
scanf("%d%d",&t1,&t2);
if(t1>t2)
{
int temp=t1;
t1=t2;
t2=temp;
}
y1 = t1/10000;
y2 = t2/10000;
m1 = t1/100-y1*100;
m2 = t2/100-y2*100;
d1 = t1-y1*10000-m1*100;
d2 = t2-y2*10000-m2*100;
while(y1<y2-1)
{
if(isLeap(y1))
{
ans+=366;
}
else
{
ans+=365;
}
y1++;
}
while(m1!=m2||d1!=d2||y1!=y2)
{
ans++;
if(d1==month[m1][isLeap(y1)])
{
if(m1==12)
{
y1++;
m1=1;
}
else
{
m1++;
}
d1=1;
}
else
{
d1++;
}
}
printf("%d",ans+1);
return 0;
}```