Week3 作业C 区间覆盖 贪心

题意:

数轴上有n个区间[ai,bi],选择尽可能少的区间覆盖一条指定线段[1,t]。要求覆盖整点,即[1,2]和[3,4]可以覆盖[1,4]。

题目分析:

贪心策略:

预处理:将与[1,t]没有交集的区间去掉,剩下的区间按a升序排列。如果最小区间的左端点>1,无解。

start为待覆盖区间的左端点,end为当前覆盖区间的右端点,选取以<=start为起点的所有区间中右端点最大的区间[ai,bi],更新start=end+1,end=bi,直到全覆盖。

证明:左端点升序排列后,在向后遍历区间时,可以找到一个位置,该位置左边的区间左端点符合要求,该位置右边的区间左端点不符合要求。在遍历所有左端点符合要求的区间时,找到右端点最大的区间,可以覆盖尽量远的区间,因此,贪心策略是正确的。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
struct range{
	int a,b;
	bool operator<(const range &r)const{
		if(a!=r.a) return a<r.a;
	}
};

int cnt;
range ran[25005];
int main()
{
	int n,t; scanf("%d%d",&n,&t);
	int a,b; int temp=0;
	for(int i=0;i<n;i++){
		scanf("%d%d",&a,&b);
		//预处理 将在1-t的区间加入 
		if(!(a>t || b<1)){
			ran[temp].a=a; ran[temp].b=b;
			temp++;
		}
	}
	bool ok=1;
	if(!temp) {ok=0; //cout<<"没有在1-t的区间\n"<<endl; 
	}
	sort(ran,ran+temp);
	
	if(ran[0].a>1){ok=0;  //cout<<"最小的左端> 1"<<endl; 
	} 
	int start=1;int end=0;
	int pos=0; int cnt=0;
	while(end<t){//未完全覆盖 
		start=end+1;
		for(int i=pos;i<temp;i++){
			if(ran[i].a<=start)
			{
				if(ran[i].b>end) end=ran[i].b;
			} 
			else{
				pos=i;break;
			} 
		}
		if(start>end){
			ok=0;
		//	cout<<"start="<<start<<" end="<<end<<endl;
			break;
		}
		else cnt++; 
	}
	if(ok==0) cout<<"-1"<<endl;
	if(end>=t) cout<<cnt<<endl;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值