程序设计思维 B - 区间选点(贪心算法)

题目

数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)

Input
第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)

Output
一个整数,代表选点的数目

Examples
Input
2
1 5
4 6
Output
1

Examples
Input
3
1 3
2 5
4 6
Output
2

思路

这道题的目的是取最少的点以使得输入的每个区间都至少含一个点。
我们将输入的区间按以下规则排序:
① 右端点的值越大越往后排
② 当右端点相同时,左端点的值越大越往后排
为了让一个点尽可能地落在多个区间内,我们应该尽量取靠后(右)的点,以使其尽可能地落在更多(排在后面)的区间中。按照这个想法,我们首先选择排在第一个区间的右端点,该点不仅落在了第一个区间中,而且是最靠后(右)的点。接着把该点落在的所有区间剔除,让剩下的区间重新排序,重复选点的过程。
以上是贪心算法的策略。这个策略之所以可行,是因为这种选点的策略总能带来最好的结果,所以贪心算法总能得到最好的结果。
下面的图可以更好地展示这个过程:
① 输入所有的区间
在这里插入图片描述
② 给区间排序
在这里插入图片描述
③ 选点
在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

using namespace std;

int n;
int cnt = 0;

vector<pair<int, int>> v;

// pair<int a, int b>
bool cmp(pair<int, int> x, pair<int, int> y)
{
	if (x.second != y.second) return x.second < y.second;
	else return x.first < y.first;
}

bool inRange(int p, pair<int, int>s)
{
	if (p<s.first || p>s.second) return false;
	else return true;
}

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) {
		int a, b;
		cin >> a >> b;
		v.push_back(make_pair(a, b));
	}

	sort(v.begin(), v.end(), cmp);

	reverse(v.begin(),v.end());

	int p = v.back().second;
	cnt++;
	
	while (v.size() != 0) {
		pair<int, int> s = v.back();
		if (inRange(p, s)) v.pop_back();
		else {
			p = s.second;
			v.pop_back();
			cnt++;
		}
	}

	cout << cnt << endl;

	return 0;
}

发布了12 篇原创文章 · 获赞 0 · 访问量 127

猜你喜欢

转载自blog.csdn.net/weixin_43826681/article/details/104842916
今日推荐