一、区间调度问题
囊括“活动调度问题”,以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
贪心可以有以下三种策略:
- 最早开始时间
- 最早结束时间
- 用时最少
分析可知,第一种策略是错误的,如果一个活动迟迟不终止,后面的活动就无法开始,不能达到题目要求的节目最多数量。而使用第三种策略,选择用时最少的,但它可能会同时和多个节目进行冲突,达不到题目要求。故应该选择第二种策略——最早结束时间。
贪心算法步骤如下:
- n个活动按结束时间排序
- 选择第一个结束的活动,并删除(或跳过)与它时间冲突的活动
- 重复步骤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个作业。
贪心策略:最长处理时间的作业优先。
- n≤m,需要的时间就是n个作业中最长的处理时间。(只要最长的作业处理完,其他均提前处理完)
- 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; } }