题意介绍
区间覆盖问题,数轴上有若干的区间,选择最少的区间能够覆盖指定线段
题意分析
做这道题的时候主要遇到两个问题:
(1)一直wa,一直不知道为什么,问了其他同学终于知道了,这道题有坑!一直认为(1,2)和(2,4)可以覆盖(1,4)线段,殊不知(1,2)和(3,4)也算是覆盖了(1,4)线段。
(2)上面的问题解决之后,运行又出现超时问题,因为需要将所有区间排序,所以可以找到所有区间的左端点的最小值和右端点的最大值,先判断最小值是否小于下线段的左端点,最大值是否大于右端点,如果这个条件不满足,直接continue就可以,满足条件再往下走。
用到一个数组来标记某个区间是否已经访问过,用now标记每次需要加入的区间,bz用来标记能否覆盖指定线段,不能覆盖跳出循环。
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define INF 0X7fffffff
struct p {
int a, b;
}d[20000000];
int N, T;
bool cmp(p p1, p p2) {
if(p1.a!=p2.a)
return p1.a < p2.a;
else return p1.b > p2.b;
}
int main() {
while (scanf("%d%d",&N,&T)!=EOF) {
int mi = INF, ma = -1;
for (int i = 0; i < N; i++) {
scanf("%d%d", &d[i].a, &d[i].b);
mi = min(mi, d[i].a);
ma = max(ma, d[i].b);
}
if (mi > 1 || ma < T) {
printf("-1\n");
continue;
}
sort(d,d+N,cmp);
int *v = new int[N];
for (int i = 0; i < N; i++) v[i] = 0;
p now;
int count = 0;
now = d[0];
v[0] = 1;
count++;
int bz = 0;
int j = -1;
while (now.b < T) {
int k = -1, M = -1;
for (int i = j + 1; i < N; i++) {
if (!v[i]) {
if (M<d[i].b&&d[i].a <= now.b + 1 && d[i].a>now.a) {
M = d[i].b;
k = i;
}
}
}
if (k == -1) {
bz = 1;
break;
}
now = d[k];
j = k;
v[k] = 1;
count++;
}
if (bz) printf("-1\n");
else printf("%d\n", count);
}
return 0;
}