【C++算法】贪心算法-区间问题,超详细注释例题讲解
贪心策略:新建一个结构体存储区间的左端点和右端点,将这N个区间按照右端点从小到大排序,遍历所有的区间,如果当前遍历到的区间左端点的值大于了上一个区间的右端点的值,说明此时区间没有重合,则区间个数+1
1)最大不相交区间数(区间选点)

- 翻译一下题目,也就是说给定
n
n
n个闭区间,问能从中选出多少个区间使其互不相交
- 贪心策略:新建一个结构体存储区间的左端点和右端点,将这
n
n
n个区间按照右端点从小到大排序,遍历所有的区间,如果当前遍历到的区间左端点的值大于了上一个区间的右端点的值,说明此时区间没有重合,则区间个数
+
1
+1
+1
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int n=1e5+5;
struct range {
int l;
int r;
}range[n];
bool cmp(range a,range b) {
return a.r<b.r;
}
int n;
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
scanf("%d%d",&range[i].l,&range[i].r);
}
int res=0;
int front_r=int_min;
sort(range+1,range+1+n,cmp);
for(int i=1;i<=n;i++) {
if(range[i].l>front_r) {
res++;
front_r=range[i].r;
}
}
cout<<res;
return 0;
}
2)区间分组

- 翻译一下题目,现在有
n
n
n个区间,问最少分多少组,能让这些分组中的所有区间两两之间包括端点都没有交集
- 贪心策略:将所有区间按照左端点从小到大排序,从前往后处理每个区间,判断是否能把这个区间放到现有的某个分组中,即判断
r
a
n
g
e
[
i
]
.
l
>
某一分组最大右端点
range[i].l \ > \ 某一分组最大右端点
range[i].l > 某一分组最大右端点
- 如果存在这样的分组(与某个分组间没有交集),则将区间 $ i $ 放进去,并且更新这个分组的最大右端点(注意,如果与多个分组都有交集则可以放到任意一个分组中,不影响结果,可自行模拟证明)
- 如果不存在这样的分组(与每个分组间都有交集),则开一个新组,再把区间
i
i
i 放进去
- 在判断当前区间是否与某一分组有交集时,只需要与所有分组中最小的分组最大右端点进行比较即可,因为这是最有可能满足
r
a
n
g
e
[
i
]
.
l
>
某一分组最大右端点
range[i].l \ > \ 某一分组最大右端点
range[i].l > 某一分组最大右端点 的情况,对于所有分组中最小的分组最大右端点,只需要用一个小根堆来维护即可
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int n=1e5+5;
struct range {
int l;
int r;
}range[n];
bool cmp(range a,range b) {
return a.l<b.l;
}
int main() {
int n;
cin>>n;
for(int i=1;i<=n;i++) {
int l,r;
scanf("%d%d",&l,&r);
range[i]={l,r};
}
sort(range+1,range+1+n,cmp);
priority_queue<int,vector<int>,greater<int>>heap;
for(int i=1;i<=n;i++) {
if(heap.empty() || heap.top()>=range[i].l) {
heap.push(range[i].r);
} else {
heap.pop();
heap.push(range[i].r);
}
}
cout<<heap.size()<<endl;
return 0;
}
3)区间覆盖

- 翻译一下题目,···,这道题没什么可翻译的
- 贪心策略:将所有区间按照左端点从小到大排序,从前往后依次枚举每个区间,在所有能覆盖
s
t
a
r
t
start
start 的区间中选择一个右端点最大的区间,然后将
s
t
a
r
t
start
start 更新成为右端点的最大值,继续向后覆盖,如果所有区间都遍历过了但并没有覆盖到
e
n
d
end
end 的话说明无法完全覆盖,则输出
−
1
-1
−1
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int n=1e5+5;
struct range {
int l,r;
bool operator<(const range &w)const {
return l<w.l;
}
}range[n];
int main() {
int st,en;
cin>>st>>en;
int n;
cin>>n;
for(int i=1;i<=n;i++) {
int l,r;
scanf("%d%d",&l,&r);
range[i]={l,r};
}
sort(range+1,range+1+n);
int res=0;
bool success=false;
for(int i=1;i<=n;i++) {
int j=i,front_r=int_min;
while(j<=n && range[j].l<=st) {
front_r=max(front_r,range[j].r);
j++;
}
if(front_r<st) {
break;
}
res++;
if(front_r>=en) {
success=true;
break;
}
st=front_r;
i=j-1;
}
if(!success) res=-1;
cout<<res;
return 0;
}
相关文章:
-
-
-
BFS是广度优先搜索(Breadth-First Search)的缩写,是一种图遍历算法。它从给定的起始节点开始,逐层地向外扩展,先访问起始节点的相邻节点,然后再访问相邻节点的相邻…
-
-
链表是一种线性数据结构,由一系列节点组成。数据域(Data):存储节点的数据。指针域(Pointer):存储指向下一个节点的地址。链表的第一个节点称为头节点(Head),最后一个节…
-
链表是通过一组任意的储存单元来存储线性表中的数据元素。为建立线性关系,每个结点需要一个指针域以及指向下一结点的指针域。带头结点链表头节点不存储数据。…
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论