c++实现——区间覆盖问题

题意

数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。

覆盖整点,即(1,2)+(3,4)可以覆盖(1,4) !!!!!!。’
刚开始以为只有(1,2)+(2,4) 才可以覆盖(1,4),导致一直WA;

不可能办到输出-1

Input

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

Output

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

Sample Input

3 10
1 7
3 6
6 10

Sample Output

2

思路

每次查找可以尽量可能大的覆盖区间的区间,直到全部区间被覆盖。

过程

首先将所有区间按左端点排序,然后选择尽可能大的区间来覆盖总区间,然后再从剩下的区间里面,选择下一个尽可能大的能覆盖剩下总区间的区间,继续下去,直到覆盖整个总区间。

代码

//这道题输入数据很多,请用scanf而不是cin cin读入比scanf慢
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct section
{//存储的区间
	int l;
	int r;
};
bool cmp(const section a,const section b)
{//比较区间的左端点
	return a.l<b.l;
}
section ans[25000];  //存储区间
int main(int argc, char** argv)
{

	int N,T;
	int count;
	while(scanf("%d %d",&N,&T)!=EOF) //读到数据尾为止
	{
		for(int i=0; i<N; i++)
		{
			scanf("%d %d",&ans[i].l,&ans[i].r);  //读入数据
		}
		sort(ans,ans+N,cmp);    //按左端点排序
		if(ans[0].l>1)
		{//相当于剪枝
		//如果按左端点升序排序 第一个最小左端点 不是1 那么则无法覆盖从1到T
			printf("-1\n");
			continue;
		}
		count=0;//选取区间个数
		int index=0,new_r=1,new_rr=0;   
		//index 区间索引  new_r 当前所在右端点 new_rr当前可到达最右端点
		while(new_rr<T)
		{//可到达的最右端点达不到T的时候 执行函数
			for(;index<N;index++)
			{//遍历区间
				if(ans[index].l<=new_r&&ans[index].r>=new_r)
				{//新的区间的做端点不能大于当前最右端点 刚开始是1 后面是new_rr+1	
					if(ans[index].r>new_rr)
					{//寻找可以到达的最右端点
						new_rr=ans[index].r;	
					}			
				}
				else if(ans[index].l>new_r)
				{//左端点超过了当前的右端点 结束遍历
					break;
				}	
			} 
			if(new_rr<new_r) break; //所能到达的右端点不会在增加 就结束寻找
			else
			{//加一个区间 并更新当前可以到达的右端点 为new_rr+1  这样才能保证
			//(1,2)+(3,4)可以覆盖(1,4);
				count++;
				new_r=new_rr+1;
			} 		
		}
		if(new_rr>=T) printf("%d\n",count);  //可以覆盖T
		else
		{//不能
			printf("-1\n");
		}	
	}
	return 0;
}

总结

注意细节!!!!!

覆盖整点,即(1,2)+(3,4)可以覆盖(1,4) !!!!!!。’
刚开始以为只有(1,2)+(2,4) 才可以覆盖(1,4),导致一直WA;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值