算法笔记 4.4 贪心 区间贪心

贪心分治动规区别

1.简单贪心

PAT B1020 月饼
PAT B1023 组个最小数

2.区间贪心

给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两之间没有交集

例如:(1,3)、(2,4)、(3,5)、(6,7) 最多选3个:(1,3),(3,5)、(6,7)

贪心算法思想:

基础两点:

a.优先选择短的区间
b.如果存在一个区间包含另一个区间,应选择更小的区间. 


算法(左端点为例)

1、对区间左端点进行从大到小排序,左端点相同按右端点从小到大排序 (右端点排序遵循b原则)
2、依次选出左端点最大的区间,当待选择区间与已选区间集合相交时,舍弃待选区间
3、首先:排好后的第一个不是原始序列的第一个。其次:每次直接从排好后的第一个开始选,也是为了使左边预留区间最大

代码:

#include		 
using namespace std;

struct Inteval
{
	int x,y;//开区间左右端点
}I[1000];

bool cmp(Inteval a,Inteval b){
	if(a.x!=b.x) return a.x>b.x;//左端点从大到小排序
	else return a.y>n){
		for(int i=0;i>I[i].x>>I[i].y;
		}
		sort(I,I+n,cmp);
		int ans=1,lastx=I[0].x;//选中x最大的第一个
		cout<<"选择以下区间:"<

 

lx:区间选点问题:

给出N个闭区间[x,y],求最少需要确定多少个点,才能使每个闭区间都至少存在一个点。例如:对闭区间[1,4]、[2,6]、[5,7]来说,需要两个点(例如3,5)。

分析:将上面不重叠区间数最多问题的I[i].y<=lastx改成I[i].y

先按左区间从大到小排好序,每个区间内都要至少包含一个点,对于左区间值最大的区间I1来说,选哪个点可以尽可能多的覆盖其他区间呢?很显然,取左端点值,因为已经排好序了,越往左,覆盖的区间数越多。每次选的都是lastx,I[i].y=lastx的区间也被覆盖了,因此将上述代码I[i].y<=lastx改成I[i].y

代码:

#include		 
using namespace std;

struct Inteval
{
	int x,y;//开区间左右端点
}I[1000];

bool cmp(Inteval a,Inteval b){
	if(a.x!=b.x) return a.x>b.x;//左端点从大到小排序
	else return a.y>n){
		for(int i=0;i>I[i].x>>I[i].y;
		}
		sort(I,I+n,cmp);
		int ans=1,lastx=I[0].x;//选中x最大的第一个
		cout<<"选择以下点:"<

贪心分治动规区别​​​​​​​

你可能感兴趣的:(算法竞赛,算法笔记,算法笔记,贪心)