您的位置:首页 > 其它

uva10020 - Minimal coverage(区间覆盖)

2014-07-26 21:41 267 查看
题目:uva10020 - Minimal coverage(区间覆盖)

题目大意:给出一些线段,然后问怎样取能使得最少的线段覆盖区间[0, M].

解题思路:先预处理掉那些和区间【0,M】不沾边的线段。

将线段按照起点小的排序。

接着遍历这些线段。首先先判断起点最小的点是否<=0,如果不满足这个说明它不能覆盖区间。

然后每次都小于等于当前覆盖的起点的最长线段,之后要将起点更新成这个最长线段的终点。然后接着判断下一条线段。如果更新了起点发现依然找不到满足条件的线段,说明不能覆盖。

最后还要看一下是否能够覆盖到M。

代码:

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;

const int N = 100005;
int m, n;
int visit
;

struct segments {

int l, r;
}s
;

int cmp (const segments& a, const segments &b) { return a.l < b.l; }

int Max (const int a, const int b) {return a > b ? a: b;}

int solve () {

memset (visit, 0, sizeof (visit));
if (s[0].l > 0)             //判断能否覆盖区间起点
return 0;
int st = 0;
int ll = -1;
int t = -1;
for (int i = 0; i < n; i++) {

if (s[i].l <= st) {  //找符合条件的最长的线段

if (ll < s[i].r) {

visit[i] = 1;
if (t >= 0)
visit[t] = 0;
t = i;
ll = Max (ll, s[i].r);
}
} else {

if (st == ll)  //更新后发现依然没有
return 0;
st = ll;       //更新起点

i--;
t = -1;        //更新起点后这个记录之前记录的线段就是确定需要,和更新后的没有关联了
}
if (ll >= m)           //能否覆盖终点
break;
}
if (ll < m)                    //能否覆盖终点

return 0;
int count = 0;
for (int i = 0; i < n; i++)
if (visit[i])
count++;
return count;
}

int main () {

int t;
int l, r;
scanf ("%d", &t);
while (t--) {

scanf ("%d", &m);
n = 0;
while (scanf ("%d%d", &l, &r), l || r) {

if (r <= 0 || l >= m)
continue;
s
.l = l;
s
.r = r;
n++;
}

sort (s, s + n, cmp);
int count = solve();
printf ("%d\n", count);
if (count) {
for (int i = 0; i < n; i++)
if (visit[i])
printf ("%d %d\n", s[i].l, s[i].r);
}
if (t)
printf ("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: