题意
数轴上有 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;
}