洛谷 P1167 刷题
洛谷 P1167 刷题
题目描述
noip
临近了,小A
却发现他已经不会写题了。好在现在离竞赛还有一段时间,小A
决定从现在开始夜以继日地刷题。也就是说小A
废寝忘食,一天二十四小时地刷题。
今天的日期(时间)是yyyyyyy**y年mmm**m月ddd**d日hhh**h时minmin分,考试的时间是yyyyyyy**y'年mmm**m'月ddd**d'日hhh**h'时minmin'分。这之间的所有时间小A
都用来刷题了,那么考试之前他最多能刷多少题呢?注意哦,考虑闰年。
时间紧张小A
只管数量不管质量。当然有的题目容易一些,有的题目难一些。根据小A
的经验,他能一眼看出写出某一个题目需要的时间,以分钟记。
现在给出洛谷Online Judge
的题目列表,请你挑出最多的题目使小A
能在竞赛前写出来。
我们假设从远古到未来,历法的表示与现在一样。
输入格式
第一行一个整数NN,表示洛谷Online Judg
e的题目数,N≤5000N≤5000。
接下来NN行,每行一个整数表示刷该题需要用的时间,以分钟记(\le 10000≤10000)。(这个题本身是什么并不重要,不是么?小A
已经写过题目数为00个)。
接下来两行依次是当前时间和竞赛时间。时间给出的格式是:yyyy-mm-dd-hh:minyyy**y−m**m−d**d−h**h:min,例如:2007-06-23-02:002007−06−23−02:00,采用2424小时制,每天从00:00~23:59,年份从00000000到99999999。
输出格式
一行,一个整数,noip
前最多刷的题目数。
输入输出样例
输入 #1复制
输出 #1复制
题解:
一道模拟题,加了一点点的贪心。
其实这题的贪心非常好想,就是时间少的先来,直接排序扫就可以。
带着这个思路,我们过来写代码:
然后我们发现我们卡在时间的处理上了...果然我还是蒟蒻
所以我在这里主要介绍一下这些“日期题”的处理技巧。
首先是读入,针对于这种读入,我们用字符串处理再从字符串中提取实在是麻烦的要命。所以我们直接用一种简化的方式:
scanf("%d-%d-%d-%d:%d",&start[1],&start[2],&start[3],&start[4],&start[5]);
scanf("%d-%d-%d-%d:%d",&endd[1],&endd[2],&endd[3],&endd[4],&endd[5]);
不用担心这种方法会爆锅,根本不可能,简单好用,骗分首选。
读入完事了,接下来我们需要把这个时间段处理成分钟数(这样才能贪心)。
我给大家介绍两种方法把这个时间段分钟数处理出来。
第一种做法:
我们以0000年1月1日的00:00分做基准线(也不知道这时候基督这小家伙出生没),分别用起始日期和结束日期减去这个基准,然后就处理出了这个时间段(有一点点前缀和的味道)
然鹅我并没有这么做
第二种做法:
实在是惭愧,本蒟蒻只能想到最朴实无华的模拟方法。你想啊,我们可以先处理出天数然后×1440(24*60,一天的分钟数),然后再处理每天的分钟。
然后我们又想到,可不可以逐次处理年月日,最后再一点点的多退少补(注意这4个字!!)呢?
当然可以!!
我们先从起始年到终止年(注意不能<=终止年而要减去1即<终止年,下同)
如果是闰年就加上366天,否则加365天。
然后我们会发现,我们多处理了起始年的前半年,少处理了终止年的前半年。
这就是多退少补的思想了。先判闰年,用两个月份数组处理。
同理,我们多处理了起始月的前半个月,少处理了终止月的前半个月。
所以我们继续多退少补。
最后处理小时和分钟。
贪心的部分我就不讲了,这道题的难点已经说完了,这道题的贪心如果想不出来还是退役多练练吧。
注意一下:我一开始WA了两个大数据的点,是因为最后输出的时候,直接在else里输出,这样如果是极大数据的话,根本就进不去else那里,导致输出为空,请大家引以为戒。
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,time,ans;
int a[5010];
int m1[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int m2[]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int start[10],endd[10];
bool check(int x)
{
if((x%4==0 && x%400!=0) || x%400==0)
return 1;
return 0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
scanf("%d-%d-%d-%d:%d",&start[1],&start[2],&start[3],&start[4],&start[5]);
scanf("%d-%d-%d-%d:%d",&endd[1],&endd[2],&endd[3],&endd[4],&endd[5]);
for(int i=start[1];i<endd[1];i++)
{
if(check(i))
time+=366;
else
time+=365;
}
if(check(start[1]))
for(int i=1;i<start[2];i++)
time-=m2[i];
else
for(int i=1;i<start[2];i++)
time-=m1[i];
if(check(endd[1]))
for(int i=1;i<endd[2];i++)
time+=m2[i];
else
for(int i=1;i<endd[2];i++)
time+=m1[i];
for(int i=1;i<start[3];i++)
time--;
for(int i=1;i<endd[3];i++)
time++;
time=time*24*60;
time-=60*start[4]+start[5];
time+=60*endd[4]+endd[5];
for(int i=1;i<=n;i++)
{
if(time>=a[i])
{
time-=a[i];
ans++;
}
else
break;
}
printf("%d",ans);
return 0;
}