Codevs 1214 线段覆盖

来源:互联网 发布:有什么好看的网络电影 编辑:程序博客网 时间:2024/05/29 17:27

传送门

看了很多人的题解,除了DP就是贪心(确实是个贪心题)

但这个优化一下就可以暴力做啊hhhhhhh。

嗯,那么我们现在看题。

题目描述 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


其实不难做,关键就在于如何划分线段覆盖的范围,以及如何选取线段。

我们可以发现线段覆盖的区间有以下几种关系:

1、包含,如 a=[1,10],b=[5,6],则b含于a,a包含b。

2、完全重合。

3、部分重合。

4、无重合部分。

我们要解决的就是在这四种情况下怎样处理线段。

对于包含关系,我们选取被包含的线段是最优的,即右端点小的线段。
对于完全重合的各个线,我们只选取一条。
对于部分重合,我们要选取对后面线段的选择影响小的,即右端点小的线段。
对于无重合部分的两条线段,我们先看它们是否与其他线段满足以上三种关系,否则都选取。

然后我们根据右端点的位置大小sort,模拟就好了。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int maxn=5005;int m,n,k,tot,ans;bool used[maxn];struct Node{    int a, b;}node[maxn];bool cmp(Node a,Node b){    return a.b < b.b;}int main(){    scanf("%d",&n);    ans=n;    for(int i=1;i<=n;i++)    {        int a,b;        scanf("%d%d",&a,&b);        a+=1000,b+=1000;//因为有负坐标        if(a>b)swap(a,b);        node[i]=(Node){a,b};    }    sort(node+1,node+n+1,cmp);    for(int i=1;i<=n;i++)    {        bool ok=false;        for(int j=node[i].a;j<node[i].b;j++)            if(used[j]==true)            {                ok=true;                break;            }        if(ok)ans--;//这条线段不能放就ans--        else for(int j=node[i].a;j<node[i].b;j++)                used[j]=true;    }    printf("%d",ans);    return 0;}
原创粉丝点击