区间选点(贪心)

问题描述

数轴上有 n 个闭区间 [ a i , b i ] [a_i, b_i] 。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)

Input

第一行1个整数N(N<=100)
第2~N+1行,每行两个整数a,b(a,b<=100)

Output

一个整数,代表选点的数目

Sample Input1

2
1 5
4 6

Sample Output1

1

Sample Input2

3
1 3
2 5
4 6

Sample Output2

2

解题思路

\hspace{17pt} 首先对于一个线段而言,如果你的整个空间是从左向后选点的话,那一定是选择线段的右端点。假设要选点的区间是 [ n , m ] [n,m] ,你选择的第一个点是 x 1 x_1 ,当 x 1 x_1 尽量靠右的时候,剩余区间 [ x 1 , m ] [x_1,m] 会最短。
\hspace{17pt} 那我们应该先选择哪个线段的右端点呢?也就是说,这些线段的排序规则如何?
\hspace{17pt} 我们选择的点是线段的右端点,而我们默认选点是在空间中从左向后选点,所以肯定要把右端点最小的排在左边。那么我们的排序规则就是右端点从小到大排序(我看到有的博客中提到当右端点相同时,左端点从大到小排,其实并没有必要)。选中一个点后,我们将包含这个点的线段都在序列中删除(或者说跳过这些线段不选点),然后选择下一个右端点。

完整代码

//#pragma GCC optimize(2)//比赛禁止使用!
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int maxn=100+1;
struct Interval
{
    int a,b;
}len[maxn];
int n,ans,temp=INT_MIN;
bool comp(Interval a,Interval b)//排序原则:按照b从小到大排序
{
    return a.b<b.b;
}
int getint()
{
    int x=0,s=1;
    char ch=' ';
    while(ch<'0' || ch>'9')
    {
        ch=getchar();
        if(ch=='-') s=-1;
    }
    while(ch>='0' && ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*s;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin>>n;
    for (int i=1; i<=n; i++)
        cin>>len[i].a>>len[i].b;

    sort(len+1,len+n+1,comp);

    for (int i=1; i<=n; i++)
    {
        if(len[i].a<=temp)//当前区间含有被已经选中的点
            continue;
        else {//当前区间没有已经选中的点,选一个新的点
            temp=len[i].b;
            ans++;
        }
    }

    cout<<ans<<endl;
    return 0;
}
发布了32 篇原创文章 · 获赞 24 · 访问量 2243

猜你喜欢

转载自blog.csdn.net/weixin_43347376/article/details/104671506