Codevs 1214 线段覆盖

传送门

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

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

嗯,那么我们现在看题。

题目描述 Description

给定x轴上的N(0

输入描述 Input Description

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

输出描述 Output Description

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

样例输入 Sample Input

3

6 3

1 3

2 5

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

0


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

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

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

2、完全重合。

3、部分重合。

4、无重合部分。

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

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

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

#include
#include
#include
#include
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;jif(used[j]==true)
            {
                ok=true;
                break;
            }
        if(ok)ans--;//这条线段不能放就ans--
        else for(int j=node[i].a;jtrue;
    }
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(贪心,模拟)