C-区间覆盖(不支持C++11)

C-区间覆盖(不支持C++11)

一、题目描述

数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1

输入

   第一行:N和T
   第二行至N+1行: 每一行一个闭区间。

输出

选择的区间的数目,不可能办到输出-1

样例输入

3 10
1 7
3 6
6 10

样例输出

2

提示

   这道题输入数据很多,请用scanf而不是cin

二、思路与算法

要求出能覆盖某一段区间的最少区间数,本题主要算法是,先将所有区间排序(以区间左端点为第一关键字升序,以区间右端点为第二关键字升序),再把[1,t]两边的区间切掉。
之后,最核心的为:每选定一个区间,将已经覆盖的部分都切掉,在能继续向下覆盖的区间中,选定最大的区间,直到[1,t]都被覆盖完成。
要注意的地方是:1.只要求整数覆盖,所以有+1的要求。
2.选定的第一个区间的起点必须是1,否则判为不可能实现。
3.重点可以超出t,例如[1,12]覆盖[1,10]

三、代码实现

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

struct period{
	int a,b;
	period(){}
	period(int aa,int bb){a=aa;		b=bb;}
	bool operator <(const period &p)const{    //重载<
		if(a!=p.a){return a<p.a;}
		else{return b<p.b;} 
	}
};

int main(){
	int N,T;
	vector<period> all(0);
	int ta,tb;
	//读入所有区间
	scanf("%d %d",&N,&T);
	for(int i=0;i<N;i++){
		scanf("%d %d",&ta,&tb);
		all.push_back(period(ta,tb));
	}
	sort(all.begin(),all.end());
	
	int s=all.size();
	//切掉[1,T]以外的部分 
	while(all.empty()==0&&all[s-1].a>T){
		all.pop_back();
		s--;
	}
	while(all.empty()==0&&all[0].a<1){
		vector<period>::iterator it=all.begin();
		all.erase(it);
		s--;
	}
	//开始选择区间
	if(all.empty()==1){printf("-1\n");	return 0;}
	int result=0;          //需要的区间总数
	if(all[0].a>1){printf("-1\n");	return 0;}
	int tmp=0,j=0;
	int latest=1,flag=0;
	while(latest<T)
	{
		int maxlen=0;  //目前长度最长区间长度 
		if(flag==0){  //flag只在第一次为0,处理第一个区间 
			flag=1;
			for(int i=0;(all[i].a==1)&&i<all.size();i++){
				tmp=all[i].b-1;
				if(maxlen<tmp){maxlen=tmp;	j=i;}
			}
			if(maxlen==0) {printf("-1\n");	return 0;}
			result++;	latest=all[j].b;
		}
		else{
			for(int i=0;(i<all.size())&&(all[i].a<=(latest+1));i++)//找当前左边界最长 
		    {	if(all[i].b>latest){
		    		tmp=all[i].b-latest;
					if(tmp>maxlen)
					{
						maxlen=tmp;
						j=i;
					}
				}				
			}
			if(maxlen==0) {printf("-1\n");	return 0;}//不存在覆盖 
			else{
				result++;
				latest=all[j].b;
			}
		} 
	}
	printf("%d\n",result);		
	return 0;
}

四、经验与总结

  1. 切记切记!!重载<时,一定要包含所有情况!当不相等时返回什么,相等时又返回什么,不然会WA!
  2. 不确定循环边界等数据的时候,可以用数据测试,跟踪数据运行情况确定边界设定是否正确,错的话该如何改。
  3. scanf时间性能比cin好,更推荐用scanf、printf。
  4. 贪心指标是贪心算法最重要的部分,贪心算法的正确性依赖指标的正确性,所以贪心指标一定要慎重选择!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值