贪心算法_区间调度问题

贪心方法:"课程安排下找最多可以上多少节课"系列问题
类似问题还有:452、605、455、253等 直接秒杀!

一、问题概述
言归正传,本文解决一个很经典的贪心算法问题 Interval Scheduling
(区间调度问题)。给你很多形如 [start, end] 的闭区间,
请你设计一个算法,算出这些区间中最多有几个互不相交的区间。

二、贪心解法:
1. 从区间集合 intvs 中选择一个区间 x,这个 x 是在当前所有区间中结束最早的(end 最小)
2. 把所有与 x 区间相交的区间从区间集合 intvs 中删除
3. 重复步骤 1 和 2,直到 intvs 为空为止。之前选出的那些 x 就是最大不相交子集

为啥选择结束最早的,这里有解释:
labuladong
引用:labuladong
在这里插入图片描述

//sort()必须时静态成员函数
static bool cmp(vector<int> a, vector<int> b){
	return a[1]<=b[1];
}
int intervalSchedule(vector<vector<int>>& intvs){
	if(intvs.empty()) return 0;
	// 按end升序排序
	std::sort(intvs.begin(), intvs.end(), cmp);
	// 至少有一个区间不相交
	int count = 1;
	// 排序后,第一个区间就是 x
	int x_end = intvs[0][1];
	for(int i = 1; i<intvs.size();i++){
		int start = intvs[i][0];
		// 当下一区间的star>=x_end时,说明没有交叉
		if(start>=x_end){
			// 找到下一个选择的区间了
			count++;
			x_end=interval[1];
		}	
	}
	return count; // count 就是最大不相交子集数
}

三、应用举例

第 435 题,无重叠区间:
我们已经会求最多有几个区间不会重叠了,那么剩下的
不就是至少需要去除的区间吗?

在这里插入图片描述

第 452 题,用最少的箭头射爆气球:
其实稍微思考一下,这个问题和区间调度算法一模一样!如果最多有 n 个不重叠的区间,那么就至少需要 n 个箭头穿透所有区间:

在这里插入图片描述

# sort的cmp函数传引用能加速,少了复制实参的过程
class Solution {
public:
    static bool cmp(vector<int>& a, vector<int>& b){
      return a[1]<=b[1];
    }
    
    // 找出多少个区间不重叠,就是需要的最小的弓箭数,因为重叠的用一根弓箭就可以了
    int findMinArrowShots(vector<vector<int>>& points) {
      if(points.empty()) return 0;
      // 按end升序排序
      std::sort(points.begin(), points.end(), cmp);
      int count = 1;
      // 第一个区间的end与后面区间的start比较
      int x_end = points[0][1];
      for(int i =1; i<points.size(); i++){
        int start = points[i][0];
        // start = end也算重叠
        if(start>x_end){
          count++;
          x_end = points[i][1]; // 更新区间的end
        }
      }
      return count;
    }
};
贪心算法多机调度问题

参考csdn博主
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

int main()
{
  int m, n;
  while (cin >> m >> n)
  {
    vector<int> task(n);
    for (int i = 0; i < n; i++)
      cin >> task[i];
    // 首先对任务处理时间排序
    sort(task.begin(), task.end());
    vector<int> cpu_queen(m);
    for (int i = 0; i < n; i++)
    {
      cpu_queen[0] += task[i];
      // 对任务处理队列排序,其实每次只需要调整第一个值,插入到后面,可以手写
      sort(cpu_queen.begin(), cpu_queen.end());
    }
    cout << cpu_queen[m - 1] << endl; // 因为经过了排序,所以是最长耗时的机器为,处理完所有任务所需的时间
  }
}
以下是一个使用C++实现贪心算法解决区间调度问题的示例代码: ```cpp #include <iostream> #include <vector> #include <algorithm> // 区间结构体 struct Interval { int start; int end; }; // 比较函数,根据结束时间排序 bool compareIntervals(Interval a, Interval b) { return a.end < b.end; } // 贪心算法解决区间调度问题 int intervalScheduling(std::vector<Interval>& intervals) { // 按照结束时间排序 std::sort(intervals.begin(), intervals.end(), compareIntervals); int count = 1; // 最少需要一个区间 int endTime = intervals[0].end; // 遍历区间,选择结束时间最早的不冲突区间 for (int i = 1; i < intervals.size(); i++) { if (intervals[i].start >= endTime) { count++; endTime = intervals[i].end; } } return count; } int main() { std::vector<Interval> intervals = {{1, 3}, {2, 4}, {3, 6}, {5, 7}, {6, 8}}; int result = intervalScheduling(intervals); std::cout << "最多可安排的任务数量: " << result << std::endl; return 0; } ``` 在这个示例中,我们定义了一个`Interval`结构体来表示区间,并实现了一个比较函数`compareIntervals`,用于根据结束时间对区间进行排序。`intervalScheduling`函数使用贪心算法解决区间调度问题,首先对区间按照结束时间进行排序,然后从第一个区间开始遍历,选择结束时间最早的不冲突区间,并计数。最后输出最多可安排的任务数量。 在主函数中,我们创建了一个包含几个区间的示例输入,然后调用`intervalScheduling`函数计算结果,并输出最多可安排的任务数量。 注意:这只是一个简单的示例,实际问题可能需要根据具体情况进行更复杂的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值