UVa10020

区间覆盖的问题。给定n个区间,覆盖[0,M],要求覆盖数最小。

采用贪心的做法。先预处理一次,左端点<0的可以直接看做从0开始,右端点<0的直接忽略掉。

设当前所覆盖的是current_l,一开始是0.从0开始处理。

因为已经对数组进行排序,若segment[0].x>0的话一定没有覆盖的。

所以开始处理的时候则第一个左端点一定是0。后面就找到最长的右端点current_r。

然后就改current_l =最长的右端点,然后在对所有左端点小于current_l的端点像一开始预处理一样,把左边的端点变为 current_l。一直到current_r >=M的时候就可以跳出循环了。

然后每次都保存一次路径。

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_NUMBER = 100006;
struct node{
	int l;
	int r;
}segment[MAX_NUMBER];
node del_segment[MAX_NUMBER];
int path[MAX_NUMBER];
bool cmp(node a,node b){
	if (a.l < b.l)
		return true;
	else
		return false;
}
int main()
{
	int test_case;
	cin >> test_case;
	cin.get();
 	while (test_case--) {
		int M;
		int numbers;
		int max_right = 0;
		cin >> M;
		for (int i = 0; i < MAX_NUMBER; i++) {
			cin >> segment[i].l;
			cin >> segment[i].r;
			if (segment[i].r > max_right)
				max_right = segment[i].r;
			if (!segment[i].l && !segment[i].r) {
				numbers = i;
				break;
			}
			if (segment[i].r <= 0)
				i--;
		}
		sort(segment,segment+numbers,cmp);
		memcpy(del_segment,segment,sizeof(segment));
		for (int i = 0; i < numbers; i++) {
			if (segment[i].l < 0)
				segment[i].l = 0;
		}
		if (segment[0].l > 0 || max_right < M) {
			cout << 0 << endl;
			if (test_case){
				cout << endl;
			}
			continue;
		}
		int current_l = 0;
		int current_r = 0;
		int j,k = 0, flag;
		int left = 0,now_path = 0;
		int has_not_found = 0;
		while (1) {
			for (j = left; j < numbers && segment[j].l <= current_l; j++) {
				if (segment[j].r > current_r){
					current_r = segment[j].r;
					path[now_path] = j;
				}
			}
			now_path++;
			current_l = current_r;
			if (current_r >= M)
				break;
			flag= 1;
			for (k = j; segment[k].l <= current_l; k++) {
				if (segment[k].r > current_l) {
					segment[k].l = current_l;
					if (flag) {
						flag = 0;
						left = k;
					}
				}
			}
			if (flag) {
				has_not_found = 1;
				break;
			}
		}
		if (has_not_found) {
			cout << 0 << endl;
			if (test_case) {
				cout << endl;
			}
			continue;
		}
		cout << now_path << endl;
		for (int i = 0;i < now_path; i++) {
			cout << del_segment[path[i]].l << " " << del_segment[path[i]].r;
			cout << endl;
		}
		if (test_case)
			cout << endl;

	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值