区间贪心问题求解

区间贪心问题求解

区间贪心个人建议按照右端点从小到大排序

具体排序规则为:

如果右端点不同,选择右端点小的那个;如果右端点相同,则看左端点,选择(右端点-左端点)差值小的那个,也就是选择左端点大的那个。
bool cmp(HH a,HH b){//HH 为上一个文档里面定义的结构体,存放一个区间的左右断点
	if(a.right!=b.right) 
		return a.right<b.right;
	else 
		return a.left>b.left;
}

原理如下:
把一个个区间看作一个个会议,左端点为会议开始时间,右端点为会议结束时间,找出最多能参加几个会议?
优先选择最早结束的会议,也就是按照右端点从小到大排序。如果结束时间相同,则选择持续时间短的那个会议,这样可以腾出更多的时间参加其他的会议。
为什么不按照左端点从小到大排序呢?
因为最先开始的会议不一定最先结束,有可能最先开始的会议直接到最后一刻才结束,那就只能参加一个会议了。
参考题目:

P1803 凌乱的yyy / 线段覆盖 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

上述问题求解代码,按照右端点进行从小到大的排序:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<string>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
struct HH{		//该结构体存放区间的左端点与右端点
	int left,right;
};
bool cmp(HH a,HH b){	//按照右端点从小到大排序
	if(a.right!=b.right) 
		return a.right<b.right;
	else	//如果右端点相同,则我们需要右端点-左端点差值小的那个,也就是左端点大的那个
		return a.left>b.left;	
}
int main(){
	int n;//确定输入的区间组数
	scanf("%d",&n);
	vector<HH> a(n);//泛型为结构体HH的数组
	for(int i=0;i<n;i++){
		scanf("%d %d",&a[i].left,&a[i].right);//输入每组区间
	}
	sort(a.begin(),a.end(),cmp);//按照自定义cmp,对a数组进行排序
	int sum=1;//数组中的第一个数,也就是结束时间最早的那个区间,一定会被选中,所以直接sum初始化为1
	int tempRight=a[0].right;//同时需要有一个标记,标记最新选中的区间的右端点,到时候要判断下一个区间的左端点是否比他大
	for(int i=0;i<n;i++){
		if(a[i].left>=tempRight){//如果说下一个区间的左端点比最新选中区间的右端点大,那就没有重叠,可以参加下一个比赛
			sum++;tempRight=a[i].right;//多一个可以参加的比赛(不重叠的区间),同时设置标志为这个区间的右端点
		}
	}
	printf("%d",sum);
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值