蓝桥杯刷题——藏匿的刺客(贪心)

368 阅读2分钟

「这是我参与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;
}