「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
这是蓝桥杯算法训练中的一道贪心题目,题目不难,但是从贪心角度去看,这是一道很好的贪心算法入门题目。能够很好的帮助我们加深对贪心算法的理解。
题目
大概说明题目意思。有一些人躲在一堆草丛中,这些草丛是连在一起的,现在有n个人,每个人都会指出在两个草丛之间有人。通过这些信息,我们需要得出这些草丛最少有几个人。以i表示1到n,每次都有人指出第li个草丛和第ri个草丛之间有人。输入第一行是n,每行输入两个数。
最后输出最少的人数。
思路
我们先用一下动态规划的思想去解这道题目,每个人的指出的两个草丛之间有人,这个是有联系的。但是我们如何将这些人所给出的信息联系起来呢?我们用表格发,我们要从第一个草丛和第二个草丛之间开始到第一个草丛和第n个草丛之间,再从第二个草丛和第三个草丛之间到第二个草丛和第n个草丛之间,以此类推,我们需要遍历n+n-1+n-2+.....+1次,这无疑是个很复杂的做法,效率太低。下面我们用贪心法来解。贪心法,每次找到最优的状态。我们通过每个人给出的ri这个数来升序排序。ri最小的那个人所说的信息开始,往后遍历,只要这个人的ri在后一个人的li和ri之间,那么后一个人就可以去去除了,因为他一定和最小ri的那个人所说的草丛可以重合了。遍历到最后这个最小ri的那个人也会被删除,然后从剩下的开始,再从最小ri的那个人开始。每次开始前,总人数加一。
代码
这里用链表来实现。
#include<bits/stdc++.h>
using namespace std;
struct seation{
int l;
int r;
};
int n;
bool cmp(seation &a, seation &b) {
return a.r < b.r;
}
int main(){
list<seation>ss;
cin>>n;
seation a;
for(int i=0;i<n;i++){
int ll;
int rr;
cin>>ll>>rr;
a.l=ll;
a.r=rr;
ss.push_back(a);
}
ss.sort(cmp);//升序排序
int ant=0;
list<seation>::iterator it = ss.begin();
while(!ss.empty()){
it=ss.begin();
int mm=it->r;
ant++;
for(;it!=ss.end();){
if(it->l<=mm&&it->r>=mm){
ss.erase(it++);
}else
it++;
}
}
cout<<ant;
return 0;
}