贪心算法,关于区间问题

来源:互联网 发布:java写一个视频播放器 编辑:程序博客网 时间:2024/06/08 04:14

贪心算法——有关区间的问题 (2012-10-23 18:14:32)转载▼标签: 贪心算法区间问题it 分类: 算法分析学习
一、独立区间问题
给n个开区间[Si,Fi], 选择尽量多的区间, 使得两两不交。典型的应用就是活动安排的问题和CPU处理进程问题。
算法: 首先按照结束时间f1<=f2<…<=fn的顺序排序,依次考虑各个活动, 如果没有和已经选择的活动冲突, 就选; 否则就不选。
正确性: 如果不选f1, 假设第一个选择的是fi,则如果fi和f1不交叉则多选一个f1更划算; 如果交叉则把fi换成f1不影响后续选择。
template
void GreedySelector(int n, Type s[], Type f[], bool A[])
{
A[1]=true;
int j=1;
for (int i=2;i<=n;i++) {
if (s[i]>=f[j]) { A[i]=true; j=i; }
else A[i]=false;
}
}

二、区间覆盖问题
1、给定一个大区间[S,F],和若干的小区间[S1,F1][S2,F2]……[Sn,Fn]。选取最少的小区间将大区间[S,F]覆 盖。
算法:将所有的区间按左端点从小到大排序,依次顺序处理每个区间。每次选择覆盖点S的区间中右端点坐标最大的一个,并将S更新为该区间的右端点坐标,直到选择的区间已包含了F为止。

2、用整数I来表示X轴上的[I-1,I]的区间,给出M(1<=M<=200)个这样的不同整数,表示M个这样的区间,要求画出几条线段覆盖所有的区间,条件是每条线段可以任意长,但是要求所画的的线段的长度之和最小,并且线段的数目不超过N(1<=N<=50)。

分析如图所示:

三、点和区间的问题
1、设有X1、X2、。。。。Xn是直线上的N个点,用固定长度的闭区间覆盖这N个点,求至少需要多少个区间?
算法:首先N个点排序,将最小的点作为固定长度的左端点,并计算出找出在这个区间中点,并标记。在剩下的点中,将最小点重新作为新的端点,重复上述操作。直至所用的点都包含在内。
int greedy(int x[],int n,int k)
{
int sum=1;
sort();
int temp=x[0];
for(int i=1;i
if(x[i]-temp>k) {sum++;temp=x[i];}
return sum;
}

2、设P={X1,X2,……,Xn}是直线上的N个点,I={I1,I2,…….,In}是直线上的M个闭区间,计算I中闭区间覆盖点集P的最少 区间数。
分析:该题的思路和上一道是一样的,将点排序,找出包含最小点并且右端点最大的区间,标记在该区间内的点。在剩余的点中重复上述的操作。

3、给定一个大区间[a,b],再给出几个小区间 ,找出满足下述条件的所含元素个数最少的集合的个数,该集合满足——对于给定的每一个区间,都至少有两个不同的整数属于该集合。
本题数据规模较大,用搜索做会超时,而动态规划无从下手。考虑贪心算法。题目意思是要找一个集合,该集合中的数的个数既要少又要和所给定的所有区间有交集。(每个区间至少有两个该集合中的数)。我们可以从所给的区间中选数,为了选尽量少的数,应该使所选的数和更多的区间有交集这就是贪心的标准。一开始将所有区间按照右端点从小到大排序。从第一个区间开始逐个向后检查,看所选出的数与所查看的区间有无交集,有两个则跳过,只有一个数相交,就从当前区间中选出最大的一个数(即右端点),若无交集,则从当前区间选出两个数,就(右端点,右端点-1),直至最后一个区间。

include //整数区间问题

using namespace std;

struct prince{

int left,right;//区间左右端点

}a[10000];

int n;

int result;//存放结果中的数

int cmp(const void *a,const void *b){

return ((prince )a).right-((prince )b).right;

}

int work(){

qsort(a+1,n,sizeof(a[0]),cmp);//按区间右端点由小到大排序

int i,j,k;

int a1,a2;

a1=a[1].right-1;a2=a[1].right;result=2;

for(i=2;i<=n;i++)

{ if(a[i].left<=a1&& a[i].right>=a2)continue;//完全包含

if (a[i].left>a2 )//完全不包含

{a1=a[i].right-1;a2=a[i].right;result=result+2;}

if (a[i].left>a1 && a[i].right>a2 && a[i].left<=a2)

  {a1=a2;a2=a[i].right;result++;}//只包含一个    }return result;

}

int main(){

freopen(“range6.in”,”r”,stdin);

freopen(“range6.out”,”w”,stdout);

cin>>n;

int i;

for(i=1;i<=n;i++)

cin>>a[i].left>>a[i].right;

cout<<work()<<endl;

return 0;

}

4、给n个闭区间[ai,bi], 在数轴上选尽量少的点,使每个区间内至少有一个点。
分析:如果可以按照所有区间的结束位置排序,结束位置相同的项,开始位置小的项在前面。从区间1到区间n进行循环,对于当前区间,若集合中的数不能覆盖它,则从区间末尾向前扫描,若当前数没在集合中出现,则将该数加入集合,直至使集合能覆盖该区间为止。

转自:http://longgongshiye.blog.163.com/blog/static/1714825972011712105027741/分享: 11
喜欢
1
赠金笔

原创粉丝点击