算法-程序设计课week3---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,意味着我们可以从头往后“赶”,不断解决一个个的子问题。每次遍历都要取能够覆盖前面从起点算起的最大区间。

这道题一个好处在于目标区间从1开始,如果目标区间起点不确定就更复杂了。

#include<algorithm>
#include<cstdio>
using namespace std;
//一开始读题失误了,误以为第一行输入的是目标区间,实际上第一行是区间数和目标区间的终点
//这道题跟上一道题差不多,只是情况比较多,需要细细考虑
//当然,用手画出图形进行循环遍历仍然是很好的获得解题思路的方法
struct node {
	int a,b;
	bool operator < (const node& y) {
		return
		    (a<y.a)
		    ||
		    (a==y.a&&b<y.b);
	}
};
int main() {
	//freopen("inc.txt","r",stdin);
	int n,t;
	while(~scanf("%d %d",&n,&t)) {
		node* a=new node[n];
		int sum=0;
		bool flag=true;
		for(int i=0; i<n; i++) {
			scanf("%d %d",&a[i].a, &a[i].b);
		}
		sort(a,a+n);
		int count=1;

		//首先进行起点的判断,起点达不到要求直接退出
		int next_start=1;//由于此值需要参加最终比较,因此放在外面声明
		if(a[0].a>1)  {
//			printf("-1");
			count=-1;
		} else {

			//使用贪心法,循环地获得下一个小区间,也就是不断求解子问题
			int start=1;//每次循环从这里开始,该值不断变化

			for(int i=0; i<n; i++) {
				//如果当前区间没有覆盖点当前起点,证明覆盖当前起点的区间选择到了最优情况
				//开始对下一个起点进行遍历
				if(start<a[i].a) {
					start=next_start;

					//如果当前区间无法覆盖新的当前起点(也就是上一个区间的终点)
					//证明这个区间和上一个区间之间存在缝隙,退出
					if(next_start<a[i].a) {
						count=-1;
						break;
					}
					count++;
				}

				//如果当前区间可覆盖当前起点,则该区间内部无需遍历
				//该区间终点可能作为下一个起点进行遍历
				if(start>=a[i].a && start<=a[i].b && next_start<a[i].b+1)
					next_start=a[i].b+1;

				if(next_start>t)break;//结束条件
			}
		}
		if(next_start<=t)count=-1;
		printf("%d\n",count);
		delete[] a;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值