题意:FJ希望它的牛做一些清洁工作。有N只牛和T个时间段,每只牛可以承担一段时间内的工作。FJ希望让最小数量的牛覆盖整个T,求出其数量。若无法覆盖整个T,则输出-1.
分析:首先要注意T表示T个时间段,也就是说1就是一个时间段,而[1, 2]是两个时间段。在这个问题上,我们要做到的是用最小的牛覆盖整个区间。比较容易想到的是先将牛按开始时间排序,因为如果一开始就覆盖不了那么后续就没有意义可以直接输出-1。贪心选取在满足当前开始时间的前提下,其结束时间的大的牛,因为在满足开始前提下,当然是覆盖得越多越好。可以简单设想如果可以用一只覆盖得比较小的牛来做到最优结果,那么用覆盖得最大的必然也是最优结果。
因此算法的简单实现如下:先对牛按开始时间排序,然后用一个finalTime表示当前上一只牛的结束时间(初始化为0)。对于接下来的每一只牛,检查其开始时间是否满足不大于上一次结束时间+1。在这个前提下,选取最大的结束时间。这样就能得到最优结果。若在这个过程,无法找到一只牛满足条件,则表示无法覆盖整个空间(因为牛是按开始时间排序的,现在覆盖不了,后面的更加覆盖不了)。
1 #include <cstdio> 2 #include <algorithm> 3 4 using namespace std; 5 6 typedef pair<int, int> P; 7 8 const int MAX_N = 25000; 9 const int MAX_T = 1000000; 10 11 //输入 12 int N, T; 13 P a[MAX_N]; 14 15 //每次选取开始时间不大于当前结束时间,及其结束时间最大的牛 16 void solve(){ 17 //贪心 18 int ans = 0; //结果 19 int finalTime = 0; //当前结束时间 20 //按开始时间排序 21 sort(a, a + N); 22 for(int i = 0; i < N && finalTime < T;){ 23 int maxFinal = a[i].second, tmp = i; 24 //找符合开始时间的前提下,结束时间最大的牛 25 while(i < N && a[i].first <= finalTime + 1){ 26 maxFinal = max(maxFinal, a[i].second); 27 i ++; 28 } 29 if(tmp == i || finalTime >= maxFinal){ 30 //无法找到合适的牛 31 printf("-1 "); 32 return; 33 } 34 35 ans ++; 36 finalTime = maxFinal; 37 } 38 if(finalTime < T) 39 printf("-1 "); 40 else 41 printf("%d ", ans); 42 } 43 44 int main(int argc, char const *argv[]){ 45 46 scanf("%d %d", &N, &T); 47 for(int i = 0; i < N; i ++) 48 scanf("%d %d", &a[i].first, &a[i].second); 49 solve(); 50 51 return 0; 52 }