AcWing 907. 《算法基础课》贪心--区间覆盖
原题链接
简单
作者:
藕丝泥霸
,
2024-01-07 20:17:30
,
所有人可见
,
阅读 46
贪心思路
- 思路:
- 将区间按照左端点从小到大进行排序
- 从前往后枚举每个区间,在所有覆盖start的区间中,选择右端点最大的区间,即 max{r[i],区间i能覆盖start}
- 如何判断区间覆盖完成?
- 保证区间能连续覆盖:每次枚举选择的区间都要覆盖start,即选择的右端点r>=start
- 保证区间能覆盖完成:若出现选择的区间其右端点r>=end,说明区间覆盖完成
- 上面两个条件缺一不可,是区间覆盖完全的充要条件(体现在代码中:初始success为false,当区间覆盖完成success为true)
- 证明:
- cnt>=ans: 按照贪心思路,在有解的情况下,一定能覆盖区间,所用区间数cnt>=ans(最优解)
- 若存在一种方案,每次枚举选择的区间m其右端点不是最大的,那么后续选择的区间n其左端点一定小于同样贪心解下选择区间的左端点,此时可以将该选择方案替换为贪心解方案,即贪心方案可以由任意合法方案转换得到
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
struct Range{
int l,r;
bool operator< (const Range& d) const{
return l<d.l;
}
}range[N];
int n;
int st,ed;
int main(){
scanf("%d%d",&st,&ed);
scanf("%d",&n);
for(int i=0;i<n;i++){
int l,r;
scanf("%d%d",&l,&r);
range[i]={l,r};
}
sort(range,range+n);
bool success=false;
int res=0;
for(int i=0;i<n;i++){
int j=i,r=-2e9;
while(j<n && range[j].l<=st){
r=max(r,range[j].r);
j++;
}
if(r<st) {
success=false;
break;
}
res+=1;
if(r>=ed) {
success=true;
break;
}
st=r;
i=j-1;
}
if(!success) puts("-1");
else printf("%d\n",res);
return 0;
}