来源:http://poj.org/problem?id=2376
题意:有一些奶牛,每只奶牛负责一个时间段。问覆盖完全部的时间段最少需要多少只奶牛。若不能全部覆盖,输出-1.
思路:类似于区间覆盖的问题,明知道用贪心求解,但是还是wa了好几次。首先这道题有一个需要注意的就是每次不需要从上一只的结束点开始,可以从上一只结束的下一个点开始。比如说第一只的时间段是1 3,则第二只可是是4 7。首先排序,若开始点不等,则按开始点从小到大排序,否则按结束点从小到大排序。排好序后,第一个点肯定选,依次选择后面的点。选择点的时候,选最优的,即在符合条件的范围内,选择一个结束点最大的。这样即可。
代码:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <climits>
#include <algorithm>
using namespace std;
const int N = 25005;
struct intversal{
int begin,end;
}aa[N];
bool cmp(intversal a,intversal b){
if(a.begin == b.begin)
return a.end < b.end;
return a.begin < b.begin;
}
int main(){
//freopen("1.txt","r",stdin);
int n,T;
while(scanf("%d%d",&n,&T) != EOF){
for(int i = 0; i < N; ++i){
aa[i].begin = INT_MAX;
aa[i].end = INT_MAX;
}
for(int i = 0; i < n; ++i)
scanf("%d%d",&aa[i].begin,&aa[i].end);
sort(aa,aa+n,cmp);
if(aa[0].begin > 1){
printf("-1\n");
continue;
}
int ans = 1,id = 0;
for(int i = 0; i < n; ){
int cnt = 0;
for(int j = i + 1; j < n; ++j){
if(aa[j].begin > aa[id].end + 1)
break;
if(aa[j].begin >= aa[id].begin && aa[j].end >= aa[id].end + 1){
if(aa[j].end > aa[cnt].end)
cnt = j;
}
}
if(cnt == 0){
i++;
}
else{
id = cnt;
ans++;
i = id;
}
}
if(aa[id].end == T){
printf("%d\n",ans);
}
else
printf("-1\n");
}
return 0;
}