区间不相交问题
问题描述
给出N个开区间(x,y),从中尽可能选出多的开区间,使这些开区间两两不相交。
例如区间(1,3)、(2,4)、(3,5)、(6,7)
解决方案
把所有开区间按照左端点从大到小进行排序,左端点相同时按照右端点从小到大进行排序,按这样的顺序依次选出不相交的区间。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=110;
struct Interval {
//左右端点
int x,y;
} I[MAXN];
bool cmp(Interval a,Interval b) {
//左端点从大到小排序,相同情况按右端点从小到大排序
return a.x!=b.x?a.x>b.x:a.y<b.y;
}
int main() {
int n;
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%d%d",&I[i].x,&I[i].y);
}
sort(I,I+n,cmp);
//开区间不相交问题
puts("开区间不相交问题");
int lastX=I[0].x,count=1;
printf("当前区间:%d %d\n",I[0].x,I[0].y);
for(int i=1; i<n; i++) {
//如果右端点小于等于上一个左端点,说明不相交
if(I[i].y<=lastX) {
printf("当前区间:%d %d\n",I[i].x,I[i].y);
//更新上一节点的位置,次数加一
lastX=I[i].x;
count++;
}
}
printf("个数:%d\n",count);
return 0;
}
输出结果如下
区间选点问题
问题描述
给出N个闭区间[x,y],求需要的最少点的个数,可以使得每个区间范围内都至少存在一个点。
例如区间[1,4]、[2,6]、[5,7]
解决方案
通过思考可以发现这个问题和上述区间不相交问题策略一致,只需要在上述排序条件后,每次取区间的左端点即可,但是由于是闭区间,需要把<=修改为<,其余代码不用变
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=110;
struct Interval {
//左右端点
int x,y;
} I[MAXN];
bool cmp(Interval a,Interval b) {
//左端点从大到小排序,相同情况按右端点从小到大排序
return a.x!=b.x?a.x>b.x:a.y<b.y;
}
int main() {
int n;
scanf("%d",&n);
for(int i=0; i<n; i++) {
scanf("%d%d",&I[i].x,&I[i].y);
}
sort(I,I+n,cmp);
puts("闭区间选点问题");
int lastX=I[0].x,count=1;
printf("当前区间:%d %d\n",I[0].x,I[0].y);
for(int i=1; i<n; i++) {
//如果右端点小于上一个左端点,说明该区间范围内还没有点
if(I[i].y<lastX) {
printf("当前区间:%d %d\n",I[i].x,I[i].y);
//更新上一节点的位置,次数加一
lastX=I[i].x;
count++;
}
}
printf("个数:%d\n",count);
return 0;
}
输出结果如下