线段覆盖 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold
题解
题目描述 Description
给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)
输入描述 Input Description
输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标
。
输出描述 Output Description
输出第一行是一个整数表示最多剩下的线段数。
样例输入 Sample Input
3
6 3
1 3
2 5
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
0<N<100
思路:
贪心。我的方法是,从小到大开始遍历区间,如果下一个区间在前一个内,那么left和right设置成这次的小区间并n–;如果下一个区间和前一个区间相交叉,那么摒弃这次的。即left和right不变,只n–。 其中right刚开始要设置初值为-1,表示找到第一个区间,left和right设置为此区间,然后进行和下一个区间比较。
代码:
#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#include<stdio.h> using namespace std;struct Fo{ int y; struct Fo *next;};int main(){ struct Fo *p[2010];//以结构体角标为线段左端点,结构体元素y为右端点 int n; scanf("%d", &n); for (int i = 2; i<2010; i++){ p[i] = new Fo; p[i]->next = NULL; } for (int i = 1; i <= n; i++){ int a, b; scanf("%d %d", &a, &b); a += 1000;//题目要求(-999,999)所以加上1000排除负角标 b += 1000; if(a>b){a ^= b;b ^= a;a ^= b;}//a和b进行交换 struct Fo *q = p[a]; while (q->next)q = q->next;//赋值操作 q->next = new Fo; q->next->y = b; q->next->next = NULL; } int left, right=-1;//初始化-1 for (int i = 2; i < 2010; i++){ struct Fo *q = p[i]->next; while (q){ if (i<right){//这里两种情况,一种i在此时最大区间左边,或者右边。如果右边,那肯定不会相交. if (q->y <= right){ left = i; right = q->y; } n--; }else{ left = i; right = q->y; } q = q->next; } } PRintf("%d", n);//输出剩余区间 return 0;}新闻热点
疑难解答