POJ2376贪心

题意:数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1,t](1<=t<=1,000,000)。
覆盖整点,即[1,2]+[3,4]可以覆盖[1,4]。
不可能办到:输出-1

题解:本题为一题区间覆盖贪心问题

区间覆盖贪心题型:n个[ai,bi]区间,选择尽可能少的区间覆盖指定区间[s,t]。

贪心策略:左端点从小到大排序

贪心过程:设置一个变量end表示已覆盖到的区间右端点,另一个变量start为当前已覆盖到的区间右端点。

在所有左端点小于等于start的线段中,选择右端点最大的线段,更新end,并且初始化start=end+1,重复以上操作。

如果end<start,意味着end在下一段区间没法被更新,即不可能形成完整区间覆盖,因此跳出while。一般用while循环

贪心证明:要求用最少的线段进行覆盖,那么选取的线段必然要尽量长,而已覆盖到的区域之前的地方已经不用考虑了,能够使得线段更长取决于右端点,每次只要保证右端点尽可能大即可。


#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int inf = 0x3f3f3f3f;
struct node {
    int l;
    int r;
}p[30000];
bool cmp(node a, node b)
{
    if (a.l == b.l)return a.r > b.r;
    return a.l < b.l;
}
int main(void)
{
    ios::sync_with_stdio(false);
    int N, T;
    cin >> N >> T;
    for (int i = 1; i <= N; i++)
        cin >> p[i].l >> p[i].r;
    sort(p + 1, p + N + 1, cmp);
    int start, ans = 0, i = 1, end = 0;//end表示当前这一区间能延伸到最远位置
    while (end < T)
    {
        start = end + 1;//下一个区间的起点是上一个区间的终点+1
        for (; i <=N ; i++)
        {
            if (p[i].l <= start)
                end = max(end, p[i].r);
            else break;//如果p[i].l在start之后,则认为是下一个区间
        }
        if (end < start)
        {
            ans = -1;
            break;
        }
        ans++;
    }
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/ZJNU-huyh/p/13184868.html