POJ 2376 Cleaning Shifts 贪心
Description
Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning chores around the barn. He always wants to have one cow working on cleaning things up and has divided the day into T shifts (1 <= T <= 1,000,000), the first being shift 1 and the last being shift T.
Each cow is only available at some interval of times during the day for work on cleaning. Any cow that is selected for cleaning duty will work for the entirety of her interval.
Your job is to help Farmer John assign some cows to shifts so that (i) every shift has at least one cow assigned to it, and (ii) as few cows as possible are involved in cleaning. If it is not possible to assign a cow to each shift, print -1.
Each cow is only available at some interval of times during the day for work on cleaning. Any cow that is selected for cleaning duty will work for the entirety of her interval.
Your job is to help Farmer John assign some cows to shifts so that (i) every shift has at least one cow assigned to it, and (ii) as few cows as possible are involved in cleaning. If it is not possible to assign a cow to each shift, print -1.
Input
* Line 1: Two space-separated integers: N and T
* Lines 2..N+1: Each line contains the start and end times of the interval during which a cow can work. A cow starts work at the start time and finishes after the end time.
* Lines 2..N+1: Each line contains the start and end times of the interval during which a cow can work. A cow starts work at the start time and finishes after the end time.
Output
* Line 1: The minimum number of cows Farmer John needs to hire or -1 if it is not possible to assign a cow to each shift.
Sample
Sample Input 3 10 1 7 3 6 6 10 Sample Output 2
题意:
有N头牛。让一些牛去做家务,然后一天分成T个时间点,也就是一天的时间点是区间[1,T]。要实现任何一个时间点都有牛在做家务。现在给出每头牛的工作时间,问你能否用最少的牛满足他的要求,即用最少的时间段覆盖掉这一天([1,T])。如果不能满足则输出-1,否则输出最少的牛数量。
思路:
先找出时间段是从1开始的,如果没有,则直接输出-1。如果有,找结束时间最大的。
然后除了选出来的第一个,将剩下的结束时间从大到小排序,如果结束时间相同,按开始时间从小到大排序。
用一个变量标记最后当前最后的时间,然后如果开始时间大于记录的时间,则选出,更新当前最后时间,如果当前时间大于等于T则结束循环。
(这个时间复杂度接近O(n2),并不是最优解,不过还是能过的)
代码:
#include<stdio.h> #include<stack> #include<algorithm> #include<queue> #include<iostream> #include<string.h> #include<string> using namespace std; struct node { int begin; int end; } cow[250100]; bool cmp(struct node a,struct node b) { if(a.begin==b.begin) return a.end>b.end; else return a.begin<b.begin; } bool cmp1(struct node a,struct node b) { if(a.end==b.end) return a.begin<b.begin; else return a.end>b.end; } int main() { int n,m; int sum=1,max=0; scanf("%d%d",&n,&m); //cin>>n>>m; for(int i=0; i<n; i++) scanf("%d%d",&cow[i].begin,&cow[i].end); sort(cow,cow+n,cmp);//找出第一个时间。 if(cow[0].begin!=1) printf("-1"); else { max=cow[0].end; sort(cow+1,cow+n,cmp1);//剩余的按照结束时间排序从大到小,如果结束时间一样,按开始时间从小到大 for(int j=1; j<n; j++) { if(max>=m) break; for(int i=1; i<n; i++) if(cow[i].begin<=max+1) { sum++;//记录用的牛数 max=cow[i].end;//记录当前的最大值 break; } } if(max>=m) printf("%d",sum); //cout<<sum; else //cout<<"-1"; printf("-1"); } }
修改:
看完大牛的代码,果然是厉害,用O(n)就可以解决了。
按照开始时间升序排列 如果 开始时间相同 按照结束时间升序排列
设t为最终结束时间,区间[1, t]为最终区间
一次1 to n的循环 同时 扩大区间,最后比较t和T的值即可
即每一次记录下上一次结束的时间,如果开始时间小于上一次的结束时间,然后更新右区间,找到最大的。