本题可理解为用N个线段去覆盖1-T的数轴,求最少使用的线段数。贪心算法每次都取当前的最佳值,适用本题。不少人想当然,认为每次用最长的线段来填,直到填满。举个反例:T为10,N为5,(1,2)、(3,8)、(9,10)、(1,6)、(6,10),按照上面的思路则取线段顺序为(3,8)、(1,6)、(6,10),需要3条线段,这并不是最短的。其实,每次应在满足条件的情况中选取终点最大的那条,如此则选(1,6)、(6,10)就够了。值得一提的是本题端点间的区间不需要覆盖,如(1,2)、(3,8)可以完全覆盖(1,8)。原题链接
#include <stdio.h>
#include <algorithm>
#include <utility>
const int maxn=25001;
using namespace std;
int main(){
int N,T,k=0,pos=0 ; ///pos初始为0,当作前面一个区间的末尾
pair<int,int> cow[maxn]; ///存储每个区间的始末点
scanf("%d %d",&N,&T);
while(N--) {
scanf("%d %d",&cow[k].second,&cow[k].first); ///second是起点,first是终点,便于排序
k++;
}
sort(cow,cow+k); ///sort()是key值从小到大排序
int ans=0;
while(pos<T){
int id=0;
for(int i=k-1;i>=0;i--) if(pos+1>=cow[i].second){ ///注意,两个shift之间不必覆盖
pos=cow[i].first;
cow[i].second=T+1; ///用完后,起点置为不可到达的数
ans++;id=1;
break;
}
if(!id) {ans=-1;break;} ///若区间断了,则不能满足题目条件
}
printf("%d\n",ans);
return 0;
}