• P1167 刷题


    题目描述

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

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

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

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

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

    输入格式

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

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

    接下来两行依次是当前时间和竞赛时间。时间给出的格式是:yyyy-mm-dd-hh:min,例如:2007-06-23-02:00,采用24小时制,每天从00:00  23:59,年份从0000到9999

    输出格式

    一行,一个整数,noip前最多刷的题目数。

    输入输出样例

    输入 #1
    2
    1
    1
    2007-06-23-11:59
    2007-06-23-12:00
    输出 #1
    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)



  • 相关阅读:
    Vue 环境配置
    导入解决方案错误及其解决办法
    Dynamics 365创建用户提示:您正在尝试使用已由其他用户使用的域登录来创建用户。的解决办法
    iOS核心动画详解(CABasicAnimation)
    iOS核心动画详解(一)
    iOS 微信支付流程详解
    初探runtime
    iOS之block,一点小心得
    iOS scrollview循环播放加缩放
    用程序删除工程中多余的图片
  • 原文地址:https://www.cnblogs.com/jiangyuechen/p/12416591.html
Copyright © 2020-2023  润新知