挑战程序设计竞赛 2章习题 poj 2376 Cleaning Shifts

地址  http://poj.org/problem?id=2376

 

题目大意是 给出 N个区间 ,询问最小需要选择几个区间能覆盖 1~T的全部区间
第一行输入 N和 T
后面N行 每行2个数字 表示区间的起点和终点
要求输出一行 选择的最小区间个数 若无法覆盖全部区间 则输出-1

Sample Input
3 10
1 7
3 6
6 10
Sample Output
2

 

解法 

贪心  将所有区间按照起点排序

选择能覆盖当前点且结束最迟的区间 然后更新当前点到选择的区间最迟的坐标 继续选择

本来以为是一个区间覆盖的模版题,结果wa了一下午,poj没有数据提,偏偏样例还能过

看了别人的题解才发现 1~5 6~10居然也算是覆盖了1~10全区间  这个没数据真看不出来

对于示例 就是

排序后的区间是  1-7 3-6 6-10

最开始我们需要找到覆盖坐标1的最优区间 就是1-7

我们取了一个区间 然后找到覆盖坐标8的最优区间 就是6-10。此时取了两个区间已经覆盖了1-10的全部坐标。 

答案为2

 

代码如下

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <stdio.h>

using namespace std;

const int N = 1000010;

/*
Sample Input

3 10
1 7
3 6
6 10
Sample Output

2
*/
int n;
struct Range
{
    int l, r;
    bool operator< (const Range& W)const
    {
        return l < W.l;
    }
}range[N];

int main()
{
    int st, ed;
    scanf("%d%d", &n, &ed);
    st = 1;
    for (int i = 0; i < n; i++)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        range[i].l = l; range[i].r = r;
    }

    sort(range, range + n);

    int res = 0;
    bool success = false;
    for (int i = 0; i < n; i++)
    {
        int j = i, r = -2e9;
        //所有区间起点在当前点前的  取终点最远的那个区间
        while (j < n && range[j].l <= st)
        {
            r = max(r, range[j].r);
            j++;
        }
        //如果所有区间都在当前点之前  那就无法覆盖了 返回-1 跳出
        if (r < st)
        {
            res = -1;
            break;
        }
        //选择区间个数加1
        res++;
        //选择后的所有区间已经覆盖到终点或者终点之后  那就得到了答案了
        if (r >= ed)
        {
            success = true;
            break;
        }
        //更新当前点 继续下一轮寻找可覆盖的区间
        st = r + 1;
        i = j - 1;
    }

    if (!success) res = -1;
    printf("%d\n", res);

    return 0;
}

 

posted on 2021-03-24 17:33  itdef  阅读(62)  评论(1编辑  收藏  举报

导航