您的位置:首页 > 其它

算法竞赛入门经典:第八章 高效算法设计 8.17 贪心之选择不相交区间

2015-08-19 09:21 218 查看
/*
选择不相交区间:
数轴上有n个开区间(ai,bi)。尽量选择多个区间,使得这些区间两两没有公共点

分析:
假设有两个区间x,y。区间x完全包含y。应选x。
按照bi从小到大的顺序给区间排序。

贪心策略:
一定要选第一个区间?
区间排成:b1<=b2<=b3...
情况1:
a1>a2,区间2包含区间1,此时应选区间1,a1>ai,不选i
情况2:
a1<=a2<=a3,区间1与区间2完全不相交:
                            相交  :如果不选区间2,,黑色部分无影响,区间1有效部分变成灰色部分,被区间2包含,所以区间2不能选。不能因为选任何区间放弃
							        区间1,所以选择区间1.

实现:
选择区间1后,需要把所有和区间1相交的区间排除在外,需要记录上一个被选择的区间编号。排序后只需要扫描一次即可完成贪心过程
输入:
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
输出:
5
*/

/*
关键:
1 通过区间的右值进行比较 	bool operator < (const Section& sec)//自定义比较函数,以右区间进行比较
	{
		return iEnd < sec.iEnd;
	}
2 if(sec[i].iBeg >= sec[iCur].iEnd)//或者后区间的左值>=前区间的右值,符合
*/

#include <stdio.h>
#include <algorithm>

#define MAXSIZE 1024

using namespace std;

typedef struct Section
{
	bool operator < (const Section& sec)//自定义比较函数,以右区间进行比较
	{
		return iEnd < sec.iEnd;
	}
	int iBeg;
	int iEnd;
}Section;

int selectDisjointSection(Section* sec,int n)
{
	int iCur = 0;
	int iCount = 1;
	int i = 1;
	for(int i = 1 ; i < n ; i++)
	{
		if(sec[i].iBeg >= sec[iCur].iEnd)//或者后区间的左值>=前区间的右值,符合
		{
			iCur = i;
			iCount++;
		}
	}
	return iCount;
}

void process()
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		Section sec[MAXSIZE];
		for(int i = 0 ; i < n ; i++)
		{
			scanf("%d %d",&sec[i].iBeg,&sec[i].iEnd);
		}
		sort(sec,sec+n);
		printf("%d\n",selectDisjointSection(sec,n));
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: