区间覆盖:数轴上有 n 个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]。c++

区间覆盖

数轴上有 n 个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t];不可能办到输出-1。
输入第一行:N和T
第二行至N+1行: 每一行一个闭区间
输出选择的区间的数目,不可能办到输出-1

sample input:
3 10
1 7
3 6
6 10

sample output:
2

思路:

  1. 对于每一头牛的区间都有起始时间和结束时间,所以创建结构体用来存储每一头牛的时间区间;由于要进行贪心必须先对时间进行排序,所以需要重写操作符或者重写比较函数,重写操作符在G++11上可能会出现CE错误,可以根据自己的编译环境选择。
  2. 由于指定线段从1开始,所以在排序之后第一个区间肯定是从1开始的,他也是必须要取到的,所以在初始化定义的时候可以直接将begin和ans定义为1;
  3. 依次遍历所有的区间,如果当前区间的起始点比现有的起始点小,证明当前的区间覆盖起始点,为了寻找尽量少的区间,要选取更大的终点作为新的终点,也就是说要选取更长的一条
  4. 若遍历过程中发现当前的区间起始点比现在的起点要大,那么就要判断当前的区间起点能否和现在的结尾接上,如果接不上说明错误,数轴中间有空白没有办法用区间进行覆盖;如果能接上则选择两个中最大的终点进行更新。
  5. 结束条件为更新后的终点超过给定线段的右端点,说明能完全覆盖。
  6. 注意:本题要求是整点覆盖,也就是说区间[1,3]和[4,7]是可以覆盖闭区间[1,7]的。体现在代码中设置新的起始点时begin=end+1
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;

struct cow
{
	int begin;
	int end;
//	operator < (const cow &c) const
//	{
//		if(begin!=c.begin)
//		return (begin< c.begin);
//		else return end > c.end;
//	}	
 };
 bool cmp(cow a, cow b)
 {
 	if(a.begin!=b.begin)	return a.begin<b.begin;
 	else return a.end>b.end;
 }
int main()
{
	int n=0,t=0;
	cin>>n>>t;
	cow m[n];
	for(int i=0;i<n;i++)
	{
		cin>>m[i].begin>>m[i].end;
	}
//	sort(m,m+n);
	sort(m,m+n,cmp);
	int begin=1,end=1;
	int ans=1;
	for(int i=0;i<n;i++)
	{
		int tempb=m[i].begin;
		int tempe=m[i].end;
		if(i==0&&tempb>1) break;//第一段时间(0)必须从1开始 
		if(tempb<=begin)//当前区间覆盖起始点
			end=max(tempe,end);//那么终点就是包括起点的最长线段的终点 
		if(tempb>begin)
		{
			ans++;
			begin=end+1;//重新设置起始点
			if(tempb<=begin) 
				end=max(tempe,end);
			else break;
		}
		else if(end>=t)//超过范围 
		break; 
	}
	if(end<t)	cout<<"-1"<<endl;
	else	cout<<ans<<endl;
	return 0;
 }
发布了29 篇原创文章 · 获赞 1 · 访问量 954

猜你喜欢

转载自blog.csdn.net/qq_44654498/article/details/104675086