uva10020解题报告

本题大意: 给定一个定区间[m,n], 再给出一系列的区间[Ai, Bi] 求出最少需要几个区间[Ai,Bi] 组合起来才能覆盖定区间[m,n] 

解题思路: 这种区间问题,可以用贪心算法来求解,为了优化时间复杂度。我们在输入数据时进行预处理、把那些Ai>=m或者Bi<=n的区间去掉。在处理区间时,先进行排序,排序的好处就是加快后面的贪心算法时获取最优解得速度。当然不用也没问题。


Ac代码如下:(cmp函数可以简化,不用判断左值是否相等也是没问题的,个人习惯而已)

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 100000+100;

struct Node {
	int l;
	int r;
}list[MAXN], ans[MAXN];


int cmp(const void*p1, const void * p2) {
	Node n1 = *(Node*)p1;
	Node n2 = *(Node*)p2;
	if (n1.l!=n2.l)
		return n1.l - n2.l;
	return n1.r - n2.r;
}

void solve(int nCnt, int left, int right) {
	
	// 先进行一次排序 加快贪心获取速度
	qsort(list, nCnt, sizeof(list[0]), cmp);
	int rCnt = 0;// 结果个数
	// 采用贪心算法 每次获取r值最大且满足l<=0的
	int rMax = left;
	bool find; // 用来记录每一次轮循是否成功找到“最优解” 
	int index =0; // 记录上一次找到的最优解得下标 (加快查找速度) 
	for (;;) {
		
		find = false;
		for (int i = index; i< nCnt; ++i) {
			if (list[i].l<=left && list[i].r> rMax) {
				rMax = list[i].r;
				index = i;
				find = true;
			}
		} 
		// 如果找到最优解 更新左值范围 并把找到的点记录到结果里面 
		if (find) {
			left = list[index].r;
			ans[rCnt++] = list[index++]; 
			if (list[index-1].r>= right) {
				cout<< rCnt<< endl;
				for (int i =0; i< rCnt; ++i)
					cout<<ans[i].l<<" "<< ans[i].r<<endl;;
				return;
			}
		} else {
			// 输出结果
			cout<<0<<endl; 
			return ;
		} 	
	} 
}


int main() {
	
	int t;
	cin>>t;
	while (t--) {
		
		int k ;
		cin>>k;
		int l, r;
		int nCur= 0; // 表示当前共获取了几个节点 
		while (scanf("%d%d", &l, &r)) {
			if (!l && !r)
				break;
			if (l>=k || r<=0) // 进行预处理 
				continue;
			list[nCur].l = l;
			list[nCur++].r = r;
		}
		solve(nCur,0, k);
		
		if (t)
			cout<<endl;
	} 
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值