codevs线段覆盖 动态规划

来源:互联网 发布:mac电脑删除软件 编辑:程序博客网 时间:2024/05/17 07:35

题目描述 Description

    给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。

输入描述 Input Description

    输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。

输出描述 Output Description

    输出第一行是一个整数表示最多剩下的线段数。

样例输入 Sample Input

3

6  3

1  3

2  5

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

0<N<100

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#define inf -99999999 using namespace std;int x[100];int y[100];int b[100]={0};int main(){    int n,k;int sum=0;    cin>>n;    for(int i=1;i<=n;i++)    {        cin>>x[i]>>y[i];        if(x[i]>y[i])        {            swap(x[i],y[i]);        }    }    for(int i=1;i<=n-1;i++)//循环为线段排序:横坐标小的在前,横坐标相等的纵坐标小的在前     {        k=i;        for(int j=i+1;j<=n;j++)        {            if((x[k]>x[j])||((x[k]==x[j])&&(y[k]>y[j])))            {                k=j;            }         }        if(k!=i)        {            swap(x[i],x[k]);            swap(y[i],y[k]);        }    }    //下面是代码的核心部分,三重优化     int temp=x[1];    for(int i=2;i<=n;i++)    {        if(x[i]==temp) b[i]=1;    else temp=x[i];    }     //第一重:横坐标相同的归于一类,后面几个因为纵坐标比该类第一个大,故包含第一个,标记为1     for(int i=1;i<=n;i++)    {    for(int j=1;j<=n;j++)    {    if((i!=j)&&((x[i]<x[j])&&(y[i]>y[j]))) b[i]=1;       }    }    //第二重: 两层for循环扫一遍,存在彻底包含关系的,将包含的那一组标记为1         int l=inf-1,r=inf;//l和r就是两个参照物,类似于无穷大的一个概念     for(int i=1;i<=n;i++)    {    if(b[i]==0)        {            if(x[i]>=r)            {                sum=sum+1;                l=x[i];                r=y[i];            }        }    }     //第三重:排除交叉覆盖,即你中有我我中有你的可能,一重循环即可     cout<<sum<<endl;}


0 0
原创粉丝点击