程序设计思维与实践 Week3 作业B - 区间选点

题意

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

Input

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

Output

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

Example

Input
2
1 5
4 6
Output
1

Input
3
1 3
2 5
4 6
Output
2

思想

此类区间选点问题与区间不相交问题的策略是一致的, 如图:
首先看图a,如果闭区间I1被闭区间I2包含,那么在I1中取点可以保证这个点一定在I2内。接着把所有区间按照左端点从大到小排序,去除掉区间包含的情况,就可以得到图b。显然,由于每个闭区间中都需要存在一个点,因此对左端点最大的区间I1来说,取哪个点可以让它尽可能的覆盖其他区间?很显然,只要取左端点即可,这样这个点就可能覆盖到尽可能多的区间。由此写一个排序函数,应用可得正确答案。
在这里插入图片描述

总结

贪心算法是求解一类最优化问题的方法,它总是考虑在当前状态下局部最优或较优的策略,来使全局的结果达到最优或较优。贪心算法适用的问题一定满足最优子结构性质,使用时,需注意题意是否满足。

代码

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=110;
struct iteval
{
	int x,y;//左右开区间端点 
}ite[maxn];
bool cmp(iteval a,iteval b)
{
	if(a.x!=b.x) return a.x>b.x; //先按左端点从大到小排序
	else return a.y<b.y; //左端点相同的按照右端点从小到大排序 
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d%d",&ite[i].x,&ite[i].y);
	sort(ite,ite+n, cmp); //区间排序
	int ans=1,lastx=ite[0].x;//ans记录不相交区间的个数,lastx记录上一个被选中的区间的左端点 
	for(int i=1;i<n;i++)
	{
		if(ite[i].y<lastx) //如果该区间右端点在lastx左边 
		{
			lastx=ite[i].x; //以ite[i]作为新选中的区间 
			ans++; 
		}
	 } 
	 printf("%d\n",ans);
	return 0;
}
发布了4 篇原创文章 · 获赞 0 · 访问量 212

猜你喜欢

转载自blog.csdn.net/qq_45337415/article/details/104763918