UVa 10020 - Minimal coverage

  题目大意:以[L, R]的形式给出线段的左右端点,给出一些线段,判断是否能完全覆盖区间[0, m],如果能,算出所需线段的最小个数并输出线段。

  区间覆盖问题,用贪心策略。“ 突破口是区间包含和排序扫描,不过要先进行一次预处理,每个区间在[s, t](对应本题的[0, m])外的部分都应该先被切掉。在预处理后,在相互包含的情况下,小区间显然不应该被考虑。把各区间按照左边界从大到小排序。如果区间1的起点不是s, 无解,否则选择起点在s的最长区间。选择区间[ai, bi]后,新的起点应该设置为bi,并且忽略所有区间在bi之前的部分,就像预处理一样。”  ——摘自《算法竞赛入门经典》

  虽然说的意思明白,可是写代码的时候还是没什么头绪,只好搜代码了,有点思路后再比葫芦画瓢,还差得远啊...

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <climits>
 4 using namespace std;
 5 #define MAXN 100000+10
 6 
 7 struct Line 
 8 {
 9     int l, r;
10 };
11 
12 Line line[MAXN];
13 int selected[MAXN];
14 
15 bool cmp(const Line a, const Line b)
16 {
17     if (a.l != b.l)   return a.l < b.l;
18     return a.r < b.r;
19 }
20 
21 int main()
22 {
23 #ifdef LOCAL
24     freopen("in", "r", stdin);
25     freopen("out", "w", stdout);
26 #endif
27     int N;
28     scanf("%d", &N);
29     while (N--)
30     {
31         int m;
32         scanf("%d", &m);
33         int n = 0;  // the number of lines
34         while (1)
35         {
36             scanf("%d%d", &line[n].l, &line[n].r);
37             if (line[n].l == 0 && line[n].r == 0)   break;
38             n++;
39         }
40         sort(line, line+n, cmp);
41         int p = 0;
42         int start, end = 0;
43         int ans = 0;
44         bool ok = true;
45         while (end < m)
46         {
47             start = end;
48             int q = p;
49             int upper = INT_MIN;  // the upper bound of interval whose lower bound <= "start" and upper bound is upperest
50             int t;
51             while (p < n && line[p].l <= start)
52             {
53                 if (line[p].r > upper)
54                 {
55                     upper = line[p].r;
56                     t = p;
57                 }
58                 p++;
59             }
60             if (p == q || upper <= start)  // if p=q, thers isn't line whose left end is less than start, thus can cover
61             {
62                 ok = false;
63                 break;
64             }
65             end = upper;
66             selected[ans] = t;
67             ans++;
68         }
69         if (ok)
70         {
71             printf("%d\n", ans);
72             for (int i = 0; i < ans; i++)
73                 printf("%d %d\n", line[selected[i]].l, line[selected[i]].r);
74         }
75         else printf("0\n");
76         if (N)   printf("\n");
77     }
78     return 0;
79 }
View Code

  其中p=q时说明剩下的线段中最小线段的起点>start,无解;upper <= start是说明裁剪线段后没有剩下线段了,无解。

  今天看了点别人的博客,看来要想在acm上有点长进,全力投入一段时间是必须的,不能再走马观花似的那样三心二意了。然后就是,其实很早就发现了,现在还停留在别人二年或者三年前的水平,都快毕业的人了...无地自容啊,大牛就更不敢比了,唉,要好好努力了

posted @ 2013-07-24 16:00  xiaobaibuhei  阅读(398)  评论(0编辑  收藏  举报