区间覆盖问题-贪心求解

题目

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;
} ```

原创文章 46 获赞 1 访问量 1522

猜你喜欢

转载自blog.csdn.net/weixin_43676449/article/details/104684152
今日推荐