区间覆盖问题(贪心)

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/D
题意:

       给出一些区间[Li,Ri],请你找到这些区间的一个子集,使得子集里的区间完全覆盖[0,M].

       输入:首行输入案例数。换行后第三行包含一个数M(1<=M<=50000),其接下来每行包含一对数Li和Ri(|Li|<=50000,|Ri|<=50000),最后以"0 0"结束,案例与案例之间用换行分隔。

       输出:输出一个整数k,表示最少需要多少个区间覆盖[0,M],并在接下来的k行将这些区间按照左边数从小到大的顺序排列出。如果无解,则输出"0",不带引号。不同案例的解使用换行符间隔。

案例:

         Sample Input          

     2
     1
     -1 0
     -5 -3
     2 5
     0 0
 
     1
     -1 0
     0 1
     0 0

       Sample Output

     0
 
     1
     0 1

分析:

         将所给覆盖区间从小到大排序,先比较起点,若一致则比较终点。被覆盖区间的起点是0,那么找出所有区间起点小于0中的最合适的区间。要求用尽量少的区间覆盖,所以选择右端点更大的区间,它包含区间长度更长,更易覆盖。如果在所有覆盖区间中找到了解,但右端点小于M,则把找到的覆盖区间的右端点定为新的覆盖区间的起点。


源代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 int M;
 6 struct qj//结构体
 7 {
 8     int l;
 9     int r;
10 }a[100010],b[100010];//对象
11 int cmp(const qj &a,const qj &b)//排序
12 {
13     if(a.l!=b.l) return a.l<b.l;
14     else return a.r>b.r;
15 }
16 int main()
17 {
18     int T,x,y,j,max,ans,t;
19     scanf("%d",&T);//案例数
20     while(T--)
21     {    
22         memset(a,0,sizeof(a));
23         memset(b,0,sizeof(b));
24         int i=0,ant=0,min=0;//ant为覆盖区间数,min为覆盖区间左极限(起点)
25         scanf("%d",&M);//被覆盖区间[0,M]
26         while(scanf("%d%d",&x,&y))//给定分区间
27         {
28             if(!x&&!y) break;
29             a[i].l=x;
30             a[i].r=y;
31             i++;
32         }
33         max=0;//覆盖区间右极限(终点)
34         sort(a,a+i,cmp);//排序
35         while(1)
36         {
37             if(min>=M) break;//覆盖区间超过被覆盖区间
38             ans=0;
39             for(j=0;j<i;j++)//找寻覆盖区间
40             {
41                 if(a[j].l<=min)
42                 {
43                     if(a[j].r>max)
44                     {
45                         t=j;//标记区间
46                         max=a[j].r;
47                         ans=1;
48                     }
49                 }
50             }
51             if(ans)//判断覆盖区间是否满足条件
52             {
53                 min=max;//更改起点
54                 b[ant]=a[t];
55                 ant++;
56             }
57             else break;
58         }
59         if(ans)//输出控制
60         {
61             printf("%d
",ant);
62             for(i=0;i<ant;i++)
63                 printf("%d %d
",b[i].l,b[i].r);
64         }
65         else
66             printf("0
");
67         if(T) printf("
");
68     }
69     return 0;
70 }
原文地址:https://www.cnblogs.com/huaszjh/p/4707234.html