zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    oracle数据库查看修改字符集问题
    C/C++内存问题检查利器—Purify (五)
    C/C++内存问题检查利器—Purify (四)
    C/C++内存问题检查利器—Purify (三)
    Oracle 字符集的查看和修改
    C/C++内存问题检查利器—Purify (二)
    linux内存管理之活动内存区
    C/C++内存问题检查利器—Purify (一)
    postman——基础操作——API请求与响应——API响应
    postman——基础操作——History选项卡
  • 原文地址:https://www.cnblogs.com/ZJNU-huyh/p/13184868.html
Copyright © 2011-2022 走看看