题目描述:
三个农民每天清晨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);
}