week3作业——区间覆盖

主要思路:
一道简单的贪心应用
从左至右覆盖,R_covered记录已覆盖的区域的右端点(初始值为0)
将区间按照左端点排序(可以不用考虑右端点的顺序)
在区间集合S中选出一个右端点最大的(贪心原则)
集合S是左端点在R_covered左侧(可相等)的区间集合

执行上述循环直至(二选一):

  1. R_covered大于等于要求覆盖区间的右端点
  2. S为空集

若从1跳出循环则输出所用区间数;从2跳出则输出-1

简单的证明

选出最少的区间进行覆盖,显而易见我们要尽可能地选取长的区间。这里的“长”是指“有效长”——即超出已覆盖区域的长度,因为我们并不需要重叠的覆盖。因此,我们对区间进行排序的依据便是区间的右端点。

C - 区间覆盖

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

Input

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

Output

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

Sample Input

3 10
1 7
3 6
6 10

Sample Output

2
  • A Possible Solution
#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;

typedef struct tag_interval {
	int l, r;

	tag_interval(int L, int R) {
		l = L;
		r = R;
	}

	bool operator < (const tag_interval& x) const {
		if (l == x.l)
			return r > x.r;
		else
			return l < x.l;
	}
}interval;

int main() {
	int n,t,R_covered=0,cnt=0;
	vector<interval> v;
	scanf("%d %d",&n,&t);
	for(int i=0;i<n;i++){
		int l,r;
		scanf("%d %d",&l,&r);
		if(r>=1){
			interval tmp(l,r);
			v.push_back(tmp);
		}
	}
	sort(v.begin(),v.end());
	while(!v.empty()){
		int max=R_covered,index;
		bool flag=false;
		for(int i=0;i<v.size();i++){
			if(v[i].l<=R_covered+1&&v[i].r>max){
				index=i;
				max=v[i].r;
				flag=true;
			}
			if(v[i].l>R_covered+1)
				break;
		}
		if(flag){
			R_covered=v[index].r;
			cnt++;
			v.erase(v.begin()+index);
			if(R_covered>=t)
				break;
		}
		else{
			break;
		}
	}
	if(R_covered>=t)
		printf("%d\n",cnt);
	else
		printf("-1\n");
	return 0;
}
发布了11 篇原创文章 · 获赞 0 · 访问量 128

猜你喜欢

转载自blog.csdn.net/weixin_43669888/article/details/104810483
今日推荐