题目描述
NOIP 临近了,小 A 却发现他已经不会写题了。好在现在离竞赛还有一段时间,小A决定从现在开始夜以继日地刷题。也就是说小 A 废寝忘食,一天二十四小时地刷题。
今天的日期(时间)是 yyyy 年 mm 月 dd 日 hh 时 min 分,考试的时间是 yyyy2 年 mm2 月 dd2 日 hh2 时 min2 分。这之间的所有时间小 A 都用来刷题了,那么考试之前他最多能刷多少题呢?注意哦,考虑闰年。
时间紧张小A只管数量不管质量。当然有的题目容易一些,有的题目难一些。根据小A的经验,他能一眼看出写出某一个题目需要的时间,以分钟记。
现在给出洛谷 Online Judge 的题目列表,请你挑出最多的题目使小A能在竞赛前写出来。
我们假设从远古到未来,历法的表示与现在一样。
输入格式
第一行一个整数N,表示洛谷Online Judg
e的题目数,N≤5000
接下来N行,每行一个整数表示刷该题需要用的时间,以分钟记(≤10000)。(这个题本身是什么并不重要,不是么?小A
已经写过题目数为00个)。
接下来两行依次是当前时间和竞赛时间。时间给出的格式是:yyyy-mm-dd-hh:min,例如:2007-06-23-02:00,采用24小时制,每天从00:00 23:59,年份从0000到9999。
输出格式
一行,一个整数,noip
前最多刷的题目数。
输入输出样例
2 1 1 2007-06-23-11:59 2007-06-23-12:00
1
首先,我们采取贪心策略.也就是说,将题目花费时间从大到小排序,先挑时间短的,接着依次往长里挑选,直到超时。
最大的问题是,如何计算分钟数?输入的是两个精确日期,不能直接相减,怎么变成分钟数?
我一直认为,像日期(包括年月日)、向量(大小和方向)、学生(包括姓名、学号、身高等)此类数据的集合体,最好用结构体实现。
struct _time { int year; int month; int day; int hour; int minute; }start,finish;//要求输入的起止时间
注意这里的结构体名称没有直接用“time”,而是加了下划线。这是因为C++本来就在某个头文件里有time的定义,再定义time会冲突。这个特性坑了我好几次,每次我用“max”来表示一个什么最大值时,都会产生错误“the reference to 'max' is ambiguous”(对max的引用不明确),大概就是因为这个。
然后,我们可以以公元1年1月1日0:00作为起点,计算某个日期与它相差的天数。这里我写的函数是从我早期刚开始接触C++时编写的一个计算星期的程序里复制下来的。
int totalDays(int year, int month, int day) { int a;//当年已过的天数 int leapYear = year / 4 - year / 100 + year / 400;//闰年的总数 switch (month) { case 1: a = 0; break; case 2: a = 31; break; case 3: a = 31 + 28;//总感觉应该根据是不是闰年而判断加28还是29,但是程序输出总是正确的,不知道这是不是一个bug。 break; case 4: a = 31 + 28 + 31; break; case 5: a = 31 + 28 + 31 + 30; break; case 6: a = 31 + 28 + 31 + 30 + 31; break; case 7: a = 31 + 28 + 31 + 30 + 31 + 30; break; case 8: a = 31 + 28 + 31 + 30 + 31 + 30 + 31; break; case 9: a = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31; break; case 10: a = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30; break; case 11: a = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; break; case 12: a = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30; break; } return 365 * (year - 2 - leapYear) + leapYear*366 + a + day;//从公元1年1月1日到现在的天数 /*减2是因为,已经过去的年没有公元0年,且也不包括用户输入的年份。减去闰年数量是因为闰年单算(乘以366)。所以,“year-2-leapYear”就是平年年数。变量a存储了用户输入年份 之前,当年已经过的月份的天数*/ }
天数确定了,接下来就要将天数转化为分钟数,然后根据输入的两个日期,减去或加上一个分钟数,得到的就是我们梦寐以求的刷题时间了。
int mm(_time bef,_time aft)//计算两个日期分钟差距(不是绝对值) { int _min; int _min_bef=bef.hour*60+bef.minute; int _min_aft=aft.hour*60+aft.minute; _min=_min_aft-_min_bef; return _min; }
然后就是主程序:
int main() { // freopen("P1167.txt","r",stdin); cin>>N; for(int i=0;i<N;i++) { cin>>p[i];//每个题目用时 } sort(p,p+N);//用贪心先排序 scanf("%d-%d-%d-%d:%d",&start.year,&start.month,&start.day,&start.hour,&start.minute);//正确的输入时间 scanf("%d-%d-%d-%d:%d",&finish.year,&finish.month,&finish.day,&finish.hour,&finish.minute); long long _start=totalDays(start.year,start.month,start.day);//开始日期距公元1年1月1日的天数。下同。 long long _finish=totalDays(finish.year,finish.month,finish.day); long long minute=(_finish-_start)*1440;//一天有1440分钟 minute+=mm(start,finish); // cout<<minute<<endl; int time_total=0; int result=0,temp=0; while(time_total<=minute&&temp<N) { result++; time_total+=p[temp]; temp++; if(time_total>minute) { result--; } }//贪心选数 cout<<result; // fclose(stdin); return 0; }
(注意用sort函数要包含头文件algorithm)