区间覆盖问题

来源:互联网 发布:进出口总额 英文数据 编辑:程序博客网 时间:2024/06/04 13:40

区间覆盖问题思想:

给出数轴上的n各闭区间[a_i,b_i],选择尽量少的区间覆盖一条指定线段[s,t]。

  首先,既然目标是覆盖线段[s,t],那么每个区间在这个范围之外的部分是不起任何作用的,先将它们切去。所谓切去是指如果一个区间的左端点小于s,那么将它的左端点改为s,如果一个区间的右端点大于t,那么将它的右端点改为t。

  接着,将各个区间按照左端点从小到大的顺序排序。如果左端点最小的区间的左端点也大于s,那么可以断定该问题无解。否则,选择左端点为s的长度最长的区间,并将新的起点更新为该区间的右端点,然后重复上述过程。

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

题目简介:给定一个时间T和N个时间区间,求最少需要多少个区间覆盖总区间[1,T],无法覆盖区域[1,T]时输出-1。

例如T=10,有3个区间[1,7],[3,6],[8,10],则最少需要两个区间来覆盖,选择区间1和区间3。(整数区间,【1,7】【8,10】可以覆盖【1,10】)

分析:

①先将各区间按左端点从小到大的顺序排序

②然后再判断第一个区间是否<=start(初始为1),是进行下一步,否则覆盖失败

③遍历区间,在满足left<=start中的区间中选出右端点最大的值Max,即能覆盖最大区域的区间,并将其设为新的start

④判断Max是否>=T,是,则覆盖成功,否则循环以上步骤②③④

#include <iostream>#include <algorithm>#include <cstdio>using namespace std;long long T,N;struct Node{    long long left,right;    bool operator<(Node b)    {        if(left!=b.left)            //左端点不等,按左端点从小到大排序,相等,按右端点从大到小排序(本题可以不考虑)        return left<b.left;         else return right>b.right;    }};Node p[25005];void solve(){    int i=0,cnt=0,Max,tag;    sort(p,p+N);    if(p[0].left>1) {cout<<"-1"<<endl;return ;}       //最小的左端点不覆盖1点    int start=0;    while(1)    {        Max=0,tag=0;        for(;i<N;i++)                                 //遍历一次区间        {            if(p[i].left<=start+1)                    //遍历满足左端点<=start的区间(本题由于是整数,写成<=start+1)             {                if(p[i].right>Max)                    //储存左端点满足条件且右端点最大的区间(即覆盖最大区域)                    Max=p[i].right;                tag=1;                                //tag=1说明找到满足<=start条件的区间            }            else break;                               //一旦不满足条件,先跳出循环        }        cnt++;                                        //区间数+1        if(Max>=T) {cout<<cnt<<endl;return ;}         //如果Max>=T说明已经能完全覆盖       if(tag==0||i==N) {cout<<"-1"<<endl;return ;}  //如果tag==0或者i==N说明区间从中间断开或者结尾没有覆盖完全        //注意:上面两段不能颠倒,即先判断是否完全覆盖,再有下面的判断没有覆盖完全的情况,例:出现i==n但是却已经覆盖完全的情况       start=Max;                                    //最大的右端点作为新的起点    }}int main(){    scanf("%I64d%I64d",&N,&T);    for(int i=0;i<N;i++)    {        scanf("%I64d",&p[i].left);        scanf("%I64d",&p[i].right);    }    solve();    return 0;}


0 0
原创粉丝点击