zoukankan      html  css  js  c++  java
  • UVa 10020

      题目大意:以[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
    ", ans);
    72             for (int i = 0; i < ans; i++)
    73                 printf("%d %d
    ", line[selected[i]].l, line[selected[i]].r);
    74         }
    75         else printf("0
    ");
    76         if (N)   printf("
    ");
    77     }
    78     return 0;
    79 }
    View Code

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

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

  • 相关阅读:
    Odoo 库存管理-库存移动(Stock Move)新玩法
    odoo8.0+PyCharm4.5开发环境配置
    (总结)隐藏PHP版本与PHP基本安全设置
    Docker无法启动 Could not find a free IP address range for interface 'docker0' 最方便的解决办法
    MySQL Point in Time Recovery the Right Way
    The query below helps you to locate tables without a primary key:
    记一次揪心的MySQL数据恢复过程
    Linux中利用extundelete恢复误删除的数据
    Centos升级Python 2.7并安装pip、ipython
    navicat
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3210879.html
Copyright © 2011-2022 走看看