要覆盖[start , end]这个区间
问题描述
数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定的线段[s,t]
做法
①将所有区间 按左端点 从小到大排序
②从前往后一次枚举每个区间,在所有能覆盖shart的区间中,选择右端点最大的区间,然后将start更新成右端点的最大值。
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
struct NODE
{
int Left;
int Right;
}node[N];
bool Cmp(NODE &a, NODE &b)
{
return a.Left<b.Left;
}
int main(int argc, char** argv)
{
//读入要覆盖的区间
int Start,End;
scanf("%d%d",&Start, &End);
//读入区间总数
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d%d", &node[i].Left, &node[i].Right);
}
//按左端点从小打到排序
sort(node, node+n, Cmp);
//要用几个区间覆盖掉整个Start End
int Cnt = 0;
bool IsSuccess = false;
for(int i = 0; i < n; i++)
{
int j = i;
//MaxRight保存能覆盖Start 且 右端点最大的那个
int MaxRight = -2e9;
//保证不越界 而且可以被覆盖掉
while(j < n && node[j].Left <= Start)
{
MaxRight = max(MaxRight,node[j].Right);
j++;
}
//说明没有区间不能覆盖此区间的Start
if(j == i)
{
break;
}
//又用了一个区间
Cnt++;
//整个区间已经完全被覆盖了
if(MaxRight >= End)
{
IsSuccess = true;
break;
}
//更新区间
Start = MaxRight;
//j之前的区间不可能再去覆盖Start了 因为MaxRight是j
i = j-1;
}
if(IsSuccess)
{
cout<<Cnt<<endl;
}
else
{
cout<<"-1"<<endl;
}
return 0;
}
该博客介绍了一种算法,通过排序区间并逐步选择右端点最大的区间来覆盖指定线段的方法。首先按区间左端点升序排序,然后枚举每个区间,找到能覆盖指定起点且右端点最大的区间,更新起点并计数,直到覆盖完整个线段。代码展示了具体的实现过程。
2311





