【贪心算法(二)】三类区间问题


1介绍

本节记录了贪心算法的三类区间问题:互不相交,区间覆盖,区间选点。按照自己的思路进行了一定的解析。较为简单,不说废话了。

2互不相交_会议室问题

2.1解析

问题:有n个需要在同一天使用同一个教室的活动a1,a2,…,an,教室同一时刻只能由一个活动使用。每个活动ai都有一个开始时间si和结束时间fi 。一旦被选择后,活动ai就占据半开时间区间[si,fi)。如果[si,fi]和[sj,fj]互不重叠,ai和aj两个活动就可以被安排在这一天。

该问题就是要安排这些活动使得尽量多的活动能不冲突的举行。

(1)      依据贪心思想,每次选取最优结果,倘若每次从未举办的活动中选取活动结束时间最早的活动来举办,是否意味着在24内就能尽可能多的举办活动呢?

(2)      将数组按结束时间排序,在选择时还要确保下次开始时间大于等于本次结束时间

2.2源码

#include
using namespace std;
#define Max 10//最多活动个数  
int main(){
	int i,j,temp;//循环用
	int n;//活动个数
	int arry[Max][2];
	int sum;//活动个数
	int s=0,e=24;//一天24个小时【0,24】
	cin>>n;
	for(i=0;i>arry[i][0]>>arry[i][1];
	}
	//冒泡排序:升序
	//按结束时间排序
	for (i = 0; i < n; i++){  
        for (j = i + 1; j < n; j++){  
            if (arry[i][1]> arry[j][1]){  
                temp=arry[i][1];
				arry[i][1]=arry[j][1];
				arry[j][1]=temp;

				//整组交换
				temp=arry[i][0];
				arry[i][0]=arry[j][0];
				arry[j][0]=temp;
            }  
        }  
    }  
	//初始化赋值
	temp=arry[0][1];
	cout<<"["<24 || arry[i][0]>24)
			//break;
	}
	cout<

2.3结果

测试用例:5  ;

【2,10)【5,6)【11,13)【13,20)【19,24);

【贪心算法(二)】三类区间问题_第1张图片

3区间覆盖

3.1解析

问题:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),

求最少使用多少条线段可以将整个区间完全覆盖

(1)      既然是完全覆盖,那么必定不存在相邻区间不相交的情况,也就是相邻区间必定是相交的。比如:【1,3】【4,5】【5,6】三条区间是不可能覆盖区间【1,6】

(2)      这里所说的相邻区间指的是按左端点排序以后的各个区间。比如【1,4】【5,6】【3,5】,不能说【1,4】与【5,6】是相邻区间不相交的情况,因为先排序得到【1,4】【3,5】【5,6】所以该组三个区间不存在相邻区间不相交的情况。

(3)      比较麻烦的是下面这种情况,你需要在【3,6】【2,7】之间做一个选择:

【贪心算法(二)】三类区间问题_第2张图片

(4)      因为要选择最少的区间个数,所以应该选【2,7】。如何选择【3,6】【2,7】?循环与【1,4】相交的区间从中找出右端点最大的即可,这也是这段程序复杂的地方。

3.2源码

#include
using namespace std;
#define Max 10
int main(){
	int i,j,temp,k;//循环用
	int n;
	int m;
	int arry[Max][2];
	int sum;//总数
	int start,end;
	cout<<"总区间长度:";cin>>m;
	cout<<"线段条数:";cin>>n;
	for(i=0;i>arry[i][0]>>arry[i][1];
	}
	//冒泡排序:升序
	//左端点从小到大排
	for (i = 0; i < n; i++){  
        for (j = i + 1; j < n; j++){  
            if (arry[i][0]> arry[j][0]){ 
				temp=arry[i][0];
				arry[i][0]=arry[j][0];
				arry[j][0]=temp;
				//整组交换
				 temp=arry[i][1];
				arry[i][1]=arry[j][1];
				arry[j][1]=temp;
            }  
        }  
    }  
	//主要的逻辑计算
	//第一个必选
	sum=1;
	i=0;
	start=arry[0][0];
	end=arry[0][1];
	cout<<"("<end && arry[j][0]<=end && arry[j][1]>=endM){//相交
				endM=arry[j][1];
				i=j;
			}
			else{
				break;
			}
		}
		sum++;
		end=arry[i][1];//更新end的数值
		cout<<"("<

3.3结果

【贪心算法(二)】三类区间问题_第3张图片

测试用例A:

区间长度:8也就是【1,8】;可选区间条数:5;

区间:【1,4】【2,5】【3,5】【3,7】【6,8】

【贪心算法(二)】三类区间问题_第4张图片

4区间选点_海岸线问题

4.1解析

问题:假设海岸线是一条无限延伸的直线。陆地在海岸线的一侧,而海洋在另一侧。
每一个小的岛屿是海洋上的一个点。雷达坐落于海岸线上,只能覆盖d距离。
题目要求计算出能够覆盖给出的所有岛屿的最少雷达数目。
(1) 通过下列图来分析,更易理解
(2) 至少需要两个雷达,才能覆盖A,B岛
【贪心算法(二)】三类区间问题_第5张图片

(3)      至少需要1个雷达,才能覆盖A,B岛

【贪心算法(二)】三类区间问题_第6张图片

(4)      至少需要1个雷达,才能覆盖A,B岛

【贪心算法(二)】三类区间问题_第7张图片

4.2源码

D是用来确定该岛屿能被雷达扫射到的区间,此处直接给出该区间,免去数学计算。

#include
using namespace std;
#define Max 10
int main(){
	int i, j, temp;//循环用
	int n,sum;
	int arry[Max][2];
	int start, end;//区间开始的点和区间结束的点
	cin >> n;
	for (i = 0; i < n; i++){
		cin >> arry[i][0] >> arry[i][1];
	}
	//冒泡排序:升序
	//按左点从小到大排序
	for (i = 0; i < n; i++){
		for (j = i + 1; j < n; j++){
			if (arry[i][0]> arry[j][0]){
				temp = arry[i][0];
				arry[i][0] = arry[j][0];
				arry[j][0] = temp;
				//整组交换
				temp = arry[i][1];
				arry[i][1] = arry[j][1];
				arry[j][1] = temp;
			}
		}
	}
	//分析
	start = arry[0][0];
	end = arry[0][1];
	sum = 1;//sum是雷达个数,最少一个
	for (i = 1; i < n;i++){
		if (start<=arry[i][0] &&end>=arry[i][1]){//区间包含
			start = arry[i][0]; end=arry[i][1];
		}
		else if (end>arry[i][0] && end<=arry[i][1]){//区间相交
			start = arry[i][0];
		}
		else if (end<=arry[i][0]){//区间交集为空
			cout << "(" << start << "," << end << ")" << endl;//输出,可以不看
			sum++;
			start = arry[i][0];
			end = arry[i][1];
		}
	}
	cout << "(" << start << "," << end << ")" << endl;//输出,可以不看
	cout << "最少雷达=" << sum;
	return 0;
}

4.3结果

测试用例A:5  ;

(2,5)(6,9)(8,11)(10,11)(9,15)

【贪心算法(二)】三类区间问题_第8张图片

【贪心算法(二)】三类区间问题_第9张图片


测试用例B:4 ;

(1,5)(2,7)(3,5)(6,10)

【贪心算法(二)】三类区间问题_第10张图片

【贪心算法(二)】三类区间问题_第11张图片

5总结

比较有疑虑的地方在于,没有找到对应题目所在的网址,也就是代码没有AC过,所以我尽量编写测试用例来测试代码的准确性,目前没有发现不合理的地方。一方面要照顾输出的格式,另一方面也是为了方便读者理解,代码有一些可以优化和简洁的地方就没有做了。


你可能感兴趣的:(常用算法)