一、区间调度问题

囊括“活动调度问题”,以HDU2037为例。
Problem Description
有很多电视节目,给出他们的起止时间,有的节目时间冲突,问能完整看完的电视节目最多是多少

Input
输入数据包含多个测试实例,每个测试实例第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。

Sample Input

12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0

Sample Output

5

贪心可以有以下三种策略:

  1. 最早开始时间
  2. 最早结束时间
  3. 用时最少

分析可知,第一种策略是错误的,如果一个活动迟迟不终止,后面的活动就无法开始,不能达到题目要求的节目最多数量。而使用第三种策略,选择用时最少的,但它可能会同时和多个节目进行冲突,达不到题目要求。故应该选择第二种策略——最早结束时间

贪心算法步骤如下:

  1. n个活动按结束时间排序
  2. 选择第一个结束的活动,并删除(或跳过)与它时间冲突的活动
  3. 重复步骤2,直到活动为空。每次选择剩下的活动中最早结束的那个活动,并删除与他时间冲突的活动。
    在这里插入图片描述

如图所示,1-5已经按照end排序好(最好情况下,也就是指每个活动都没有冲突时,排序好的结果是所有节目都可以看,且是按照排序后顺序播放)只需遍历判断下一个活动是否与上一个确定活动冲突,若无冲突则可以选择,若有冲突就删除跳过。上图的最终选择结果就是1.3.5。

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

struct pro{
  int start, end;
}a[101];
int cmp(pro a, pro b) {
  return a.end < b.end;
}
int main() {
  fio
  int n;
  while (cin >> n && n) {
    for (int i = 0; i < n; i++) {
      cin >> a[i].start >> a[i].end;  
    }
    sort(a, a+n, cmp);
    /*
    for (int i = 0; i < n; i++) 
      cout << a[i].start << " " << a[i].end << endl;
    */
    int count = 0, lastend = -1;
    for (int i = 0; i < n; i++) {
      if (a[i].start >= lastend) {
        lastend = a[i].end;
        count++;
      }
    }
    cout << count <<endl;
  }
}

二、多机调度问题

Problem Description
设有n个独立的作业,由m台相同的机器进行加工处理。作业i的处理时间为ti,任何作业在被处理时不能中断,也不能进行拆分处理。要求给出一种作业调度方案,在尽可能短的时间内,由m台机器加工处理完成n个作业。

贪心策略:最长处理时间的作业优先。

  1. n≤m,需要的时间就是n个作业中最长的处理时间。(只要最长的作业处理完,其他均提前处理完)
  2. n>m,对n个作业按处理时间从大到小排序,然后按顺序分配给当前累加处理时间最少的机器。

举例分析:

设n = 6,m = 3;
各作业处理时间分别为ti :2 5 13 15 16 20;
按处理时间从大到小排序之后存入t数组:20 16 15 13 5 2;
再设一个数组mint,存放各机器累加的处理时间:

①初始0 0 0(m = 3 ,所以3个均有效)

②20 16 15(按排好序的顺序依次存入)

关键步骤:下一个作业的处理时间应该累加在当前mint数组中最小的机器中 ,此时15最小,故13累加到15上:
20 16 15+13 = 20 16 28

④同上,当前16最小,5累加到16上:
20 16+5 28 = 20 21 28

⑤同上,当前20最小,2累加到20上:
20+2 21 28 = 22 21 28

已没有需要处理的作业,完成的最短时间为三台机器中时间最长的28(28分钟内22、21一定能处理完)

代码如下:
tip:max_element和min_element的详细使用方法.

#include<bits/stdc++.h>
#define fio ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

int t[10010]; 
int mint[101];
bool cmp(const int &x, const int &y) {
  return x > y;
}
int main() {
  int num;
  cin >> num;
    while (num--) {
    int n, m;
        memset(t, 0, sizeof(t));
        memset(mint, 0, sizeof(mint));
        cin >> n >> m;
        for (int i = 0; i< n; i++)
          cin >> t[i];
        sort(t, t+n, cmp); 
        for (int i = 0; i < n; ++i)
            *min_element(mint, mint+m) += t[i];
        cout << *max_element(mint, mint+m) << endl;
    }
}