《算法笔记》学习笔记

1、题目+代码+小结

  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;
}```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值