46.贪心算法练习:  区间合并


总时间限制: 

1000ms

 

内存限制: 

65536kB

描述

给定 n 个闭区间 [ai; bi],其中i=1,2,...,n。任意两个相邻或相交的闭区间可以合并为一个闭区间。例如,[1;2] [2;3] 可以合并为 [1;3][1;3] [2;4] 可以合并为 [1;4],但是[1;2] [3;4] 不可以合并。

我们的任务是判断这些区间是否可以最终合并为一个闭区间,如果可以,将这个闭区间输出,否则输出no

输入

第一行为一个整数n3 ≤ n ≤ 50000。表示输入区间的数量。
之后n行,在第i行上(1 ≤ i ≤ n),为两个整数 ai bi ,整数之间用一个空格分隔,表示区间[ai; bi](其中1 ≤ ai ≤ bi ≤ 10000)。

输出

输出一行,如果这些区间最终可以合并为一个闭区间,输出这个闭区间的左右边界,用单个空格隔开;否则输出no

样例输入


5

5 6

1 5

10 10

6 9

8 10

样例输出


1 10

贪心代码(要用覆盖才可以):

#include

using namespace std;

#include

#include

struct QJ{

       int z,y;

};

const int INF=50001;

QJ qj[INF];

int zz=INF,yy=-INF;

int cmp(const QJ &a,const QJ &b)

{

       return a.z

}

int main()

{

       int n;

       cin>>n;

       for(int i=1;i<=n;++i)

       {

              scanf("%d%d",&qj[i].z,&qj[i].y);

              if(qj[i].z<=zz)

              zz=qj[i].z;

              if(qj[i].y>=yy)

              yy=qj[i].y;

       }

       sort(qj+1,qj+n+1,cmp);

       for(int i=2;i<=n;++i)

       {

              if(qj[1].y>=qj[i].z)

              {

                     if(qj[1].z>qj[i].z)

                     qj[1].z=qj[i].z;

                     if(qj[1].y

                     qj[1].y=qj[i].y;

               }

              if(qj[1].y

              {

                     printf("no ");

                     return 0;

              }

       }

       printf("%d %d ",zz,yy);

       return 0;

}

//反例:(1,7 与(2,3)和(4,5)会判断无法形成闭合区间

//反例 1,2  3 2,7 应该输出1,7 ,但是这样算法结果是no,这个不同于“线段覆盖那道题”要用最少的线段(用右端点拍,再用左端点判断),这个题要用所有的边,从小判断到大。

错误代码:

#include

using namespace std;

#include

const int maxn=50001;

int visit[maxn]={0};

int zz=maxn,yy=-maxn;

int main()

{

       int n;

       cin>>n;

       for(int i=1;i<=n;++i)

       {

              int a,b;

              scanf("%d%d",&a,&b);

              for(int j=a;j<=b;++j)

              visit[j]=1;

              if(a

              zz=a;

              if(b>yy)

              yy=b;

       }

       for(int i=zz;i<=yy;++i)

       {

              if(visit[i]==0)

              {

                     cout<<"no"<<endl;

                     return 0;

              }

       }

       printf("%d %d",zz,yy);

       return 0;

 }

反例:应该是存边,而不是存点,因为(1,2),(3,4),23之间,没有覆盖,却判断是成立的

原文地址:https://www.cnblogs.com/c1299401227/p/5370777.html