洛谷 P1167 刷题(题解)

题目描述

NOIP 临近了,小 A 却发现他已经不会写题了。好在现在离竞赛还有一段时间,小 A 决定从现在开始夜以继日地刷题。也就是说小 A 废寝忘食,一天二十四小时地刷题。

今天的日期(时间)是 yyyy 年 mm 月 dd 日 hh 时 MM 分,考试的时间是 yyyy2 年 mm2 月 dd2 日 hh2 时 MM2 分。这之间的所有时间小 A 都用来刷题了,那么考试之前他最多能刷多少题呢?注意哦,考虑闰年。

时间紧张小 A 只管数量不管质量。当然有的题目容易一些,有的题目难一些。根据小 A 的经验,他能一眼看出写出某一个题目需要的时间,以分钟记。

现在给出洛谷 Online Judge 的题目列表,请你挑出最多的题目使小A能在竞赛前写出来。

我们假设从远古到未来,历法的表示与现在一样。

输入格式

第一行一个整数 N,表示洛谷 Online Judge 的题目数,N≤5000

接下来N行,每行一个整数表示刷该题需要用的时间,以分钟记(≤10000)。(这个题本身是什么并不重要,不是么?小A已经写过题目数为 0 个)。

接下来两行依次是当前时间和竞赛时间。时间给出的格式是:yyyy-mm-dd-hh:MM,例如: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

 测试点5(有点长)

输入 

100
7132
5111
638
7836
3809
1278
9578
7590
8245
5903
7611
4788
6810
1510
3564
3359
6412
996
4966
9801
5807
678
9175
9386
4146
1825
4869
9384
3639
2305
8130
1178
5102
2193
1739
1643
2965
7246
7051
2416
3779
5516
4395
3418
4869
9815
6073
5015
8501
210
3966
4891
8993
2883
5513
3775
799
9986
8190
4664
4361
241
7681
6235
7153
8032
8875
19
9254
1943
2049
8302
1848
9176
8699
6579
8112
4443
5158
8833
9849
6449
3882
2753
4101
1130
9517
4540
5516
9757
1047
3314
2938
576
8635
9440
8509
8
2596
3815
2007-02-05-00:00
2007-03-28-00:00

输出 

36

思路:

1.首先确定我们的思路,多去少补,即把开始年份的一整年算上,最后再把多算的时间去掉,不算最后年份的一整年,只算多出来那一部分。

2.要处理闰年的问题,就得知道闰年的定义,然后把年份转为天数。

int ifrunnian(int x)是否为闰年
{
	if(x%4==0)
	{
		if(x%400==0) return 366;
		if(x%100==0) return 365;
		return 366;
	}
	return 365;
}

3.把月份转为天数,记得闰年的二月多加一天,还有当月份为1时,直接退出循环,郑则我们直接拿他输入的天数就行,毕竟一月一号,实际上只有一号这一天,所以就算月份不为1,循环也不能涉及最后一个月。

int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};月份数组
for(int i=1;i<m1;i++)
{
	if(m1==1) break;
	ds+=month[i];
	if(i==2&&ifrunnian(y1)==366) ds++;
}
for(int i=1;i<m2;i++)
{
	if(m2==1) break;
	de+=month[i];
	if(i==2&&ifrunnian(y2)==366) de++;
}

4。还有一点点贪心,对做题时间进行简单的排序,先做时间少的 

AC code

#include <iostream>
#include <algorithm>
using namespace std;
int n;
int q[10010];
int y1,m1,d1,h1,fen1;
int y2,m2,d2,h2,fen2;
int res;
int dd;记录年份之间差的天数

int ifrunnian(int x)闰年判断
{
	if(x%4==0)
	{
		if(x%400==0) return 366;
		if(x%100==0) return 365;
		return 366;
	}
	return 365;
}


int main()
{
	cin>>n; 
	for(int i=0;i<n;i++)
	{
		cin>>q[i];
	}
	int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};	
	scanf("%d-%d-%d-%d:%d",&y1,&m1,&d1,&h1,&fen1);
	scanf("%d-%d-%d-%d:%d",&y2,&m2,&d2,&h2,&fen2);
	sort(q,q+n);
	for(int i=y1;i<y2;i++)
	{
		dd+=ifrunnian(i);
	}
	int ds,de;
	//计算月份转天数
	for(int i=1;i<m1;i++)
	{
		if(m1==1) break;
		ds+=month[i];
		if(i==2&&ifrunnian(y1)==366) ds++;
	}
	for(int i=1;i<m2;i++)
	{
		if(m2==1) break;
		de+=month[i];
		if(i==2&&ifrunnian(y2)==366) de++;
	}
	 
	int oi=(dd+de+d2-ds-d1)*1440+(h2-h1)*60+fen2-fen1;
	for(int i=0;i<n;i++)
	{
		if(q[i]>oi) break;
		if(q[i]<=oi) res++,oi-=q[i];
	}	
	cout<<res<<endl;
	return 0;
 }  

  • 53
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值