算法提高 日期计算&算法提高 5-3日历

博客内容提及了算法提高中的日历计算问题,重点在于如何确定月份的第一天是星期几,并据此进行后续的日历打印。这是一个相对常规的算法题,主要涉及日期处理。
摘要由CSDN通过智能技术生成
算法提高 日期计算
问题描述
  已知2011年11月11日是星期五,问YYYY年MM月DD日是星期几?注意考虑闰年的情况。尤其是逢百年不闰,逢400年闰的情况。
输入格式
  输入只有一行
  YYYY MM DD
输出格式
  输出只有一行
  W
数据规模和约定
  1599 <= YYYY <= 2999
  1 <= MM <= 12
  1 <= DD <= 31,且确保测试样例中YYYY年MM月DD日是一个合理日期
  1 <= W <= 7,分别代表周一到周日
样例输入
2011 11 11
样例输出

5


#include <iostream>

using namespace std;
int pmon[13]={365,31,28,31,30,31,30,31,31,30,31,30,31};//平年月份天数表 
int lmon[13]={366,31,29,31,30,31,30,31,31,30,31,30,31};//闰年月份天数表 
int week[7]={5,6,7,1,2,3,4};//当日期晚于2011年11月11日时星期辅助数组 
int rweek[7]={5,4,3,2,1,7,6};//当日期早于2011年11月11日时星期辅助数组
bool isleap(int year)//判断是否是闰年 
{
	if(year%100==0&&year%400!=0)
		return false;
	if(year%4==0)
		return true;
	return false;
}
int nday(int yy,int mm,int dd,int flag)//flag=1计算从yy年mm月dd日到这一年末有多少天,flag=0计算到本年初有多少天 
{
	int day;
	if(flag==1)
	{		
		day=isleap(yy)?lmon[mm]-dd:pmon[mm]-dd;//计算当月到月末天数 
		for(int i=mm+1;i<=12;i++)//计算从下个月到12月所有天数 
			day+=isleap(yy)?lmon[i]:pmon[i];
	} 
	else
	{
		day=dd;//计算当月到月初天数 
		for(int i=mm-1;i>=1;i--)//计算从上个月到1月所有天数 
			day+=isleap(yy)?lmon[i]:pmon[i];	
	}
	return day;
}
int nweek(int yy,int mm,int dd)//计算某个日期是周几函数
{
	int weeky;
	if(yy<2011)//当所求年分早于2011年11月11日时 
	{
		/**比如求从2008年3月12日到2011年11月11日有几天,先求2011.11.11-2011.1.1有几天
		再求 2009-2010年有几天,再求2008.3.12-2008.12.31有几天,最后把这三个数加起来**/ 

		int day=nday(2011,11,11,0);  //计算出2011年11月11日到2011年初天数 
		for(int i=2010;i>yy;i--)    //计算出从2010年到所求年份后一年有几天 
			day+=(isleap(i)?lmon[0]:pmon[0]);
		day+=nday(yy,mm,dd,1);      //计算出所求日期到所求年份年初的
		weeky=rweek[day%7];         //最后用辅助数组求出是周几 
	}
	else if(yy>2011)//晚于2011年时道理相同 
	{
		int day=nday(2011,11,11,1);
		for(int i=2012;i<yy;i++)
			day+=(isleap(i)?lmon[0]:pmon[0]);
		day+=nday(yy,mm,dd,0);	
		weeky=week[day%7];
	}
	else//当年分等于2011年再把月份和年一样进行划分 
	{
		int day=0;
		if(mm>11)
		{
			day=dd+19;
			weeky=week[day%7];		
		}

		else if(mm<11)
		{
			day=11;
			for(int i=10;i>mm;i--)
				day+=(isleap(yy)?lmon[i]:pmon[i]);
			day+=(isleap(yy)?lmon[mm]-dd:pmon[mm]-dd);	
			weeky=rweek[day%7];
		}
		else//当月份等于11月再将日期和年份一样进行划分 
		{
			if(dd==11)
				weeky=5;
			else if(dd>11)
				weeky=week[(dd-11)%7];
			else
				weeky=rweek[(11-dd)%7];
		}
	}
	return weeky;
} 
int main()
{
	int yy,mm,dd;
	cin>>yy>>mm>>dd;
	cout<<nweek(yy,mm,dd)<<endl;
	return 0;
}


又碰到算法提高一个题发现可以和这个题用一个辅助函数,说实话这种题太无聊

只要计算出这个月第一天是周几,然后顺着往后打印就可以


算法提高 5-3日历


问题描述
  已知2007年1月1日为星期一。设计一函数按照下述格式打印2007年以后(含)某年某月的日历,2007年以前的拒绝打印。为完成此函数,设计必要的辅助函数也是必要的。
样例输入
一个满足题目要求的输入范例。
例:

2050 3
样例输出
与上面的样例输入对应的输出。
例:


数据规模和约定
  输入数据中每一个数的范围。
  例:年 2007-3000,月:1-12。

#include <iostream>

using namespace std;
int pmon[13]={365,31,28,31,30,31,30,31,31,30,31,30,31};
int lmon[13]={366,31,29,31,30,31,30,31,31,30,31,30,31}; 
int week[7]={5,6,7,1,2,3,4};
int rweek[7]={5,4,3,2,1,7,6};
bool isleap(int year)
{
	if(year%100==0&&year%400!=0)
		return false;
	if(year%4==0)
		return true;
	return false;
}
int nday(int yy,int mm,int dd,int flag)
{
	int day;
	if(flag==1)
	{		
		day=isleap(yy)?lmon[mm]-dd:pmon[mm]-dd;
		for(int i=mm+1;i<=12;i++)
			day+=isleap(yy)?lmon[i]:pmon[i];
	} 
	else
	{
		day=dd; 
		for(int i=mm-1;i>=1;i--) 
			day+=isleap(yy)?lmon[i]:pmon[i];	
	}
	return day;
}
int nweek(int yy,int mm,int dd)
{
	int weeky;
	if(yy<2011)
	{
		int day=nday(2011,11,11,0);
		for(int i=2010;i>yy;i--)
			day+=(isleap(i)?lmon[0]:pmon[0]);
		day+=nday(yy,mm,dd,1);
		weeky=rweek[day%7];
	}
	else if(yy>2011)
	{
		int day=nday(2011,11,11,1);
		for(int i=2012;i<yy;i++)
			day+=(isleap(i)?lmon[0]:pmon[0]);
		day+=nday(yy,mm,dd,0);	
		weeky=week[day%7];
	}
	else
	{
		int day=0;
		if(mm>11)
		{
			day=dd+19;
			weeky=week[day%7];		
		}

		else if(mm<11)
		{
			day=11;
			for(int i=10;i>mm;i--)
				day+=(isleap(yy)?lmon[i]:pmon[i]);
			day+=(isleap(yy)?lmon[mm]-dd:pmon[mm]-dd);	
			weeky=rweek[day%7];
		}
		else
		{
			if(dd==11)
				weeky=5;
			else if(dd>11)
				weeky=week[(dd-11)%7];
			else
				weeky=rweek[(11-dd)%7];
		}
	}
	return weeky;
} 
int main()
{
	int yy,mm,ed,day[6][7]={{0}},k=1;
	cin>>yy>>mm;
	cout<<"Calendar "<<yy<<" - ";
	if(mm<10)
		cout<<"0"<<mm<<endl;
	else
		cout<<mm<<endl;
	cout<<"---------------------"<<endl;
	cout<<"Su Mo Tu We Th Fr Sa"<<endl;
	cout<<"---------------------"<<endl;
	ed=(isleap(yy)?lmon[mm]:pmon[mm]);
	for(int i=0;i<6;i++)//将每个月份赋值到数组里
		for(int j=(i==0?nweek(yy,mm,1)%7:0);j<7;j++)
			if(k<=ed)
				day[i][j]=k++;
	for(int i=0;i<6;i++)
	{
		if(i==5&&!day[i][0])
			break;			
		for(int j=0;j<7;j++)
		{
			if(!day[i][j])
				cout<<"   ";
			else if(day[i][j]<10)//小于10右对齐
				printf("%2d ",day[i][j]);
			else//大于等于10 
				printf("%-3d",day[i][j]);		
		}
		cout<<endl;		
	}
	cout<<"---------------------"<<endl;
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值