题目
https://vjudge.net/problem/OpenJ_Bailian-2376
题目大意
本题给定两个整数n和t,n表示接下来会输入n段区间,t表示需要覆盖的区间为[1,t]。题目要求利用输入的n段区间来覆盖[1,t]段,且选取数目最小。最终需要输出最小段数,若给出的区间无法完全覆盖[1,t],则输出-1.
解题思路
本题需要用贪心的思路来求解。首先根据每段区间左端点由小到大排序,之后从第一段开始选取,若第一段起点大于1,则直接输出-1.能够覆盖起点,则继续从之后的区间中遍历左端点小于已确定区间右端点的区间,然后每次更新的maxlen表示新区间能覆盖的长度,取该长度最大的区间即为下一段确定的区间。这里要注意形如[1,2],[3,4]是可以覆盖区间[1,4]的。持续上述操作直到结束即可。中途如果遇到某次maxlen的值在遍历后仍为初始的0,说明中间某段无法被覆盖,输出-1.对于判断结束的条件,可以确定一个len,该变量用来记录每次已覆盖的区间,即每次确定maxlen后,len更新为len+maxlen。
具体代码
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int l;
int r;
}a[100005];
bool cmp(node &x,node &y)
{
return x.l < y.l;
}
int main()
{
int i,j,n,t,cnt;
while(~scanf("%d",&n))
{
scanf("%d",&t);
for(i = 0; i < n; i++)
{
scanf("%d",&a[i].l);
scanf("%d",&a[i].r);
}
sort(a,a+n,cmp);
cnt=0;
int len=0,maxlen,tmp;
int newbegin=0;
i=0;
while(len < t - 1)
{
maxlen=0;
for(i; i < n; i++)
{
if(a[i].l <= newbegin + 1)
{
if(newbegin == 0)
{
tmp = a[i].r - newbegin - 1;
}
else
{
tmp = a[i].r - newbegin;
}
if(tmp > maxlen)
{
maxlen = tmp;
j = i;
}
}
else
{
break;
}
}
if(maxlen==0)
{
cnt = -1;
break;
}
len += maxlen;
cnt++;
newbegin = a[j].r;
}
cout << cnt << endl;
}
return 0;
} ```