题目链接:http://poj.org/problem?id=2376
简单翻译:
给你一个长度为T的时间区间,区间从1开始,每一个时间点都需要有奶牛在工作,有N头奶牛,给你每个奶牛的工作区间,让你从这些奶牛中选一些奶牛,让其覆盖T这个时间区间,有两个条件
1.每个时间点都需要有奶牛工作
2.尽可能少的使用奶牛
分析
我们可以字节把题目中给定的条件就想象成一个一个的区间,让我们先想一个问题,有那么些固定的区间(可能交错,可能分离),也就是奶牛的工作区间,选择其中一些,让它们都覆盖整个大区间,也就是我们的T区间。如果是这样,我们会怎么选择。 第一印象,我们会先把长的选出来,但是其实稍微有一点贪心经验的人都能轻易的分析出这是错误的,再仔细去思考,我们要保证覆盖完整个T区间,所以我们必须要保证我们选择的小区间的开始位置,小于或者等于当前T区间剩余区域的开始位置,再满足这个条件之下,怎么使奶牛用的更少呢?那就是需要让我们本次选择的小区间覆盖T的更多的位置,所以,我们贪心的规则就是,小区间满足其开始位置小于等于T区间剩余区间的开始位置的情况下,让结束位置尽可能的远离T区间剩余的开始位置,这样的贪心规则就能得到结果了。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#define max(x,y) x > y ? x : y
#define N 25005
typedef struct{
int l,r;
}Dur;
Dur nodes[N];
int cmp(const void *a,const void *b){
return ((Dur *)a)->l-((Dur *)b)->l;
}
int main(){
int n,t;
scanf("%d%d",&n,&t);
for(int i=0;i<n;i++){
scanf("%d%d",&nodes[i].l,&nodes[i].r);
}
// 按照小区间的开始位置进行从小到大的排序。为了更容易选择合适的区间
qsort(nodes,n,sizeof(nodes[0]),cmp);
int res = 0;
// 记录当前待工作区间的开始位置。
int cur = 1;
// 记录最大的结束位置
int m = 0;
for(int i=0;i<n&&cur<=t;i++){
// 在开始位置小于等于
if(nodes[i].l <= cur){
m = max(m,nodes[i].r);
}else{
if(m >= cur){
i--;
res++;
cur = m + 1;
}else{
break;
}
}
}
if(cur <= t && m >= t){
printf("%d",++res);
}else if(cur > t){
printf("%d",res);
}else{
printf("-1");
}
}