51nod 1133 不重复的线段

题目描述:

X轴上有N条线段,每条线段有1个起点S和终点E。最多能够选出多少条互不重叠的线段。(注:起点或终点重叠,不算重叠)。
例如:[1 5][2 3][3 6],可以选[2 3][3 6],这2条线段互不重叠。

输入格式

第1行:1个数N,线段的数量(2 <= N <= 10000)
第2 - N + 1行:每行2个数,线段的起点和终点(-10^9 <= S,E <= 10^9)

输出格式

输出最多可以选择的线段数量。

输入样例

3
1 5
2 3
3 6

输出样例

2

[解题思路]
如果线段是杂乱无章的,枚举所有线段选与不选的情况,那么复杂度是 O(2n) ,无法接受。

首先明确一个问题:假设有两个区间 x,yx,y ,区间 xx 完全包含 y 。那么, 选 x是不划算的,因为 x 和 y 最多只能选一个,选 x 还不如选 y ,这样不仅区间数目不会减少,而且给其他区间留出了更多的位置。接下来,按照 bi从小到大的顺序给区间排序。

贪心策略是:一定要选第一个区间。为什么?现在区间已经排序成 b1≤b2≤b3…b1≤b2≤b3… 了,考虑 a1 和 a2 的大小关系。

情况 11 : a1>a2a1>a2 ,如图( aa ) 所示, 区间 22 包含区间 11 。 前面已经讨论过,这种情况下一定不会选择区间 22 。不仅区间 22 如此,以后所有区间中只要有一个 ii 满足 a1>aia1>ai , ii 都不要选。 在今后的讨论中, 将不考虑这些区间。

情况 22 : 排除了情况 11 , 一定有 a1≤a2≤a3≤…, 如图( b )所示。 如果区间 2和区间 1 完全不相交, 那么没有影响( 因此一定要选区间 1 ), 否则区间 1 和区间 2 最多只能 选 一个。 如果不选区间 2 , 黑色部分其实是没有任何影响的( 它不 会挡住任何一个区间), 区间 11 的有效部分其实变成了灰色部分, 它被区间 2 所 包含! 由刚才的结论, 区间 2 是不能选的。 依此类推, 不能因为选任何区间而放弃区间 1 , 因此选择区间 1 是明智的。选择了区间 1 以后, 需要把所有和区间 1 相交的区间排除在外, 需要记录上一个被选择的区间编号。 这样, 在排序后只需要扫描一次即可完成贪心过程, 得到正确结果。

CODE: 

#include<bits/stdc++.h>
using namespace std;
struct node{
	int s,e;
}a[10005];
bool cmp(node x,node y)
{
	if(x.e==y.e)
      return x.s>y.s;
	return x.e<y.e;
}
int main(void)
{
	int n,s=1;
	cin>>n;
	for (int i=0;i<n;i++)
     cin>>a[i].s>>a[i].e;
	sort(a,a+n,cmp);
	for (int i=1;i<n;i++)
	 if(a[i].e==a[i-1].e||a[i].s<a[i-1].e)
	 a[i]=a[i-1];
	else
	 s++;
	cout<<s;
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值