USACO-Section 1.2 Milking Cows【贪心算法】

题目描述:

三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。
你的任务是编一个程序,读入N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位):
最长至少有一人在挤奶的时间段。
最长的无人挤奶的时间段。(从有人挤奶开始算起)(翻译来源:NOCOW

INPUT FORMAT:

第1行:一个整数N。
第2至第N+1行:每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。
OUTPUT FORMAT:
(file milk2.out)
一行,两个整数,即题目所要求的两个答案。

SAMPLE INPUT

3
300 1000
700 1200
1500 2100

SAMPLE OUTPUT

900 300

解题思路:

先定义一个结构体数组保存开始时间和结束时间,将结构体按照开始时间排序,如果下一组数据的开始时间比当前结束时间小(或相等),则是连接起来的。
如果下一组数据的开始时间比当前结束时间大,则是断开的,判断无人挤奶的时间即可。下面附上代码。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>//包含qsort函数
int n;
struct Time{//定义一个结构体,保存开始和结束 
    int a;
    int b;
}time[5010];
int cmp(const void *p,const void *q){//实现结构体比较 
    struct Time *aa=(struct Time *)p;
    struct Time *bb=(struct Time *)q;
    return aa->a-bb->a;
}
int max1(int a,int b){//max函数(不要问我为什么用max1,后面用max定义变量,懒得改) 
    return a>b?a:b;
}
int main(){
    FILE *fin  = fopen ("milk2.in", "r");
    FILE *fout = fopen ("milk2.out", "w");
    int i;
    fscanf (fin, "%d", &n);
    for(i=0;i<n;i++){
        fscanf(fin,"%d %d",&time[i].a,&time[i].b);
    }
    qsort(time,n,sizeof(time[0]),cmp);//time数组关于开始时间排序 
    int pre=time[0].a,pro=time[0].b;//pre为当前时间的头,pre为当前时间的尾 
    int max=pro-pre,min=0;//max为最长挤奶的时间,min为最长无人挤奶的时间 
    for(i=1;i<n;i++){
        if(time[i].a<=pro){
            if(time[i].b>pro){//如果time[i]的头小于等于pre,而time[i]的尾大于等于pro,则将其连接,即将time[i].b赋值给pro; 
            pro=time[i].b;
            max=max1(max,pro-pre);//判断是否大于目前最长的挤奶时间 
        }
        }
        else{
            min=max1(min,time[i].a-pro);//time[i]的头大于pre,无法连接,则判断min与当前断点的大小 
            pre=time[i].a;
            pro=time[i].b;
            max=max1(max,pro-pre);//判断是否大于目前最长的挤奶时间 
        }
    }
    fprintf(fout,"%d %d\n",max,min);
    exit(0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值