描述
三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻。第二个农民在700时刻开始,在 1200时刻结束。第三个农民在1500时刻开始2100时刻结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300时刻到1200时刻),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300时刻(从1200时刻到1500时刻)。
你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位):
- 最长至少有一人在挤奶的时间段。
- 最长的无人挤奶的时间段。(从有人挤奶开始算起)
格式
PROGRAM NAME: milk2
INPUT FORMAT:
(file milk2.in)
Line 1:
一个整数N。
Lines 2..N+1:
每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。
OUTPUT FORMAT:
(file milk2.out)
一行,两个整数,即题目所要求的两个答案。
SAMPLE INPUT
3 300 1000 700 1200 1500 2100
SAMPLE OUTPUT
900 300
题解:
我的思路是合并重叠部分。
代码实现:
View Code
1 /*
2 ID:10239512
3 PROG:milk2
4 LANG:C++
5 */
6
7 #include<iostream>
8 #include<fstream>
9 #include<string>
10 using namespace std;
11
12 ifstream fin("milk2.in");
13 ofstream fout("milk2.out");
14
15 int a[5001][2],n;
16
17 int main()
18 {
19 int i,j;int ans1=0,ans2=0;
20 fin>>n;
21 int x=100000000,y=0,z=0,t=0;
22 for(i=1;i<=n;i++)
23 {fin>>a[i][1]>>a[i][2];
24 if(a[i][1]<x) {x=a[i][1];z=i;}
25 if(a[i][2]>y) {y=a[i][2];t=i;}
26 if(a[i][2]-a[i][1]>ans1) ans1=a[i][2]-a[i][1];}
27
28 if(n==1) {fout<<a[1][2]-a[1][1]<<" "<<0<<endl;return 0;}
29
30 for(i=1;i<=n;i++)
31 for(j=1;j<i;j++)
32 if(a[j][1]>a[i][1])
33 {swap(a[i][1],a[j][1]);swap(a[i][2],a[j][2]);}
34
35 for(i=1;i<n;i++)
36 if(a[i][2]>=a[i+1][1])
37 {a[i+1][2]=max(a[i][2],a[i+1][2]);a[i+1][1]=a[i][1];if(ans1<a[i+1][2]-a[i+1][1]) ans1=a[i+1][2]-a[i+1][1];}
38 else
39 {
40 if(ans2<a[i+1][1]-a[i][2])
41 ans2=a[i+1][1]-a[i][2];
42 }
43
44 if(t==z) ans2=0;
45 fout<<ans1<<" "<<ans2<<endl;
46 //system("pause");
47 return 0;
48
49 }
另外nocow上还有几种方法很好啊:
标记数组(哈希)
1e6的范围,开一个布尔数组完全可以,有人为TRUE,无人为FALSE,注意边界即可。最后线性扫描即可。
做些优化
预处理:
建立一个数组a。 读入,若为起点将a[i]加1,若为终点将a[i]减1。 (这时顺便找出总的起点与终点);
算法开始:
将数组扫一遍(注意从总的起点扫到总的终点),这时将x(初始为0)加上a[i]。 若遇到x由0变1,或由1变0, 将这个点计入数组ans[]。 然后再将ans扫描一遍,大家可能都想到了: 若i为奇数,a[i+1]-a[i] 应该是有人的时间间隔; 若i为偶数,反之。
哈希表的解法:
View Code
1 /*
2 ID: aikilis1
3 LANG: C
4 PROG: milk2
5 */
6 #include <stdio.h>
7 #include <memory.h>
8 int main(void)
9 {
10 int n,i,a,b,j,m1=1000000,m2=0,max[2]={0,0};
11 char hash[1000000];
12 freopen("milk2.in","r",stdin);freopen("milk2.out","w",stdout);
13 memset(hash,0,sizeof hash);
14 scanf("%d",&n);
15 for (i=0;i<n;++i)
16 {
17 scanf("%d%d",&a,&b);
18 --b;
19 if (a<m1) m1=a;
20 if (b>m2) m2=b;
21 for (j=a;j<=b;++j) hash[j]=1;
22 }
23 for (i=m1;i<m2;i+=j)
24 {
25 for (j=0;hash[i+j]==hash[i];++j);
26 if (j>max[hash[i]]) max[hash[i]]=j;
27 }
28 printf("%d %d\n",max[1],max[0]);
29 fclose(stdin);fclose(stdout);
30 return 0;
31 }