教室课程调度问题的两种解法(区间着色问题)
2012-11-16 23:44
483 查看
问题描述:假如要用很多个教室对一组课程进行调度,每节课程都有其开始时间和结束时间,我们希望使用尽量少的时间来调度所有的课程,请给出调度算法?
分析:
1、利用贪心算法来解决这个问题。
1)将课程按照其结束时间的先后顺序排序。
2)设课程集合为C,我们可以利用贪心算法先求出初始课程集合C的一个最大兼容课程子集C1(C包含C1),为集合C1的课程安排一个教室。
3)将课程集合{C-C1}作为一个新的集合,进行第1)步操作直到将所有的课程都安排完。
此算法的时间复杂度是O(n平方)
2、不利用贪心算法,而是直接根据课程开始的先后顺序和兼容情况来安排课程。(直接法)
1)将课程按照其开始时间的先后顺序排序。
2)将排好序的课程依次加入教室。对每一个即将加入的课程的规则如下:
a、从第一个教室开始检查。
b、若未被占用,就使用;若占用了,比较该教室中的最后一门课程的结束时间与将要加入的课程的开始时间,若后者大于等于前者,则将其加入该教室,并更新该教室的最后结束时间。
c、若上一个教室不能使用,就按照a中的方式检查下一个教室
d、按上述方式将所有的课程安排完毕。
此算法由于只需将课程遍历一遍,遍历的时间复杂度为O(n),排序的时间负责度为O(nlogn),故其时间复杂度为O(nlogn)。
C语言实现如下:
文件“h1.h”
文件:"ClassroomDistribution.cpp"
分析:
1、利用贪心算法来解决这个问题。
1)将课程按照其结束时间的先后顺序排序。
2)设课程集合为C,我们可以利用贪心算法先求出初始课程集合C的一个最大兼容课程子集C1(C包含C1),为集合C1的课程安排一个教室。
3)将课程集合{C-C1}作为一个新的集合,进行第1)步操作直到将所有的课程都安排完。
此算法的时间复杂度是O(n平方)
2、不利用贪心算法,而是直接根据课程开始的先后顺序和兼容情况来安排课程。(直接法)
1)将课程按照其开始时间的先后顺序排序。
2)将排好序的课程依次加入教室。对每一个即将加入的课程的规则如下:
a、从第一个教室开始检查。
b、若未被占用,就使用;若占用了,比较该教室中的最后一门课程的结束时间与将要加入的课程的开始时间,若后者大于等于前者,则将其加入该教室,并更新该教室的最后结束时间。
c、若上一个教室不能使用,就按照a中的方式检查下一个教室
d、按上述方式将所有的课程安排完毕。
此算法由于只需将课程遍历一遍,遍历的时间复杂度为O(n),排序的时间负责度为O(nlogn),故其时间复杂度为O(nlogn)。
C语言实现如下:
文件“h1.h”
#ifndef H1_H #define H1_H #include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<process.h> #include<math.h> #define MAXSIZE 100 struct Class{ int startTime; int finishTime; int flag; //a value to check whether the class is distributed, 1 denotes the class has been distributed, }; //0 the other way. void finishTimeQuickSort(Class c[], int n, int flag); void qSort(Class c[], int low, int high, int flag); int partition(Class c[], int low, int high, int flag); void classroomDistributionGreedy(Class c[], int n, int classroom[][MAXSIZE]); void printCourseDistributed(int classroom[][MAXSIZE]); void classroomDistribution(Class c[], int n, int classroom[][MAXSIZE]); #endif
文件:"ClassroomDistribution.cpp"
#include "h1.h" void timeQuickSort(Class c[], int n, int flag){ //Quick sort,when flag==1,order according to finishTime; when flag==0,order according to startTime. qSort(c, 1, n, flag); } void qSort(Class c[], int low, int high, int flag){ if(low < high){ int pivotKey = partition(c, low, high, flag); qSort(c, low, pivotKey-1, flag); qSort(c, pivotKey+1, high, flag); } } int partition(Class c[], int low, int high, int flag){ Class pivot = c[low]; while(low < high){ if(flag == 1){ while(low<high && c[high].finishTime>=pivot.finishTime){ high--; } } else{ while(low<high && c[high].startTime>=pivot.startTime){ high--; } } c[low] = c[high]; if(flag == 1){ while(low<high && c[low].finishTime<=pivot.finishTime){ low++; } } else{ while(low<high && c[low].startTime<=pivot.startTime){ low++; } } c[high] = c[low]; } c[low] = pivot; return low; } void classroomDistributionGreedy(Class c[], int n, int classroom[][MAXSIZE]){ int i, j, k, flag; //i denotes the i'th classroom, j denotes the j'th class. flag = 1; //A flag to check whether a new classroom is needed. k = 1; //The k'th class of a very classroom, initial value is 1. for(i=1; i<=n; i++){ k=1; if( flag ){ flag = 0; for(j=1; j<=n; j++){ if( !c[j].flag && classroom[i][1]==0 ){ //Find the first class of a new classroom. classroom[i][k] = j; c[j].flag = 1; //The j'th class is distributed. k++; flag = 1; } else if(!c[j].flag && (c[classroom[i][k-1]].finishTime<=c[j].startTime)){ classroom[i][k] = j; c[j].flag = 1; k++; flag = 1; } } } else{ break; } } } void printCourseDistributed(int classroom[][MAXSIZE]){ int i, j, flag; flag = 1; for(i=1; i<=6; i++){ if( flag ){ flag = 0; printf("The courses of the %d 'th classroom:\n", i); for(j=1; j<=6; j++){ if(classroom[i][j] == 0){ break; } else{ printf("%d ", classroom[i][j]); flag = 1; } } printf("\n"); } else{ break; } } } void classroomDistribution(Class c[], int n, int classroom[][MAXSIZE]){ int i, k; //i denotes the i'th course. k denotes the k's classroom. int position[MAXSIZE] = {0}; //The flag to record the last course's position added to each classroom. for(i=1; i<=n; i++){ k = 1; while(c[classroom[k][position[k]]].finishTime>c[i].startTime){ k++; } flag[k]++; classroom[k][position[k]] = i; } } int main(){ int i; Class c[7]; int classroom[MAXSIZE][MAXSIZE] = {0}; for(i=0; i<=6; i++){ c[i].flag = 0; } c[6].startTime=1; c[6].finishTime=3; c[5].startTime=2; c[5].finishTime=4; c[4].startTime=3; c[4].finishTime=5; c[3].startTime=4; c[3].finishTime=6; c[2].startTime=5; c[2].finishTime=7; c[1].startTime=6; c[1].finishTime=8; //Test values. c[0].startTime=0; c[0].finishTime=0;//Initiate class values. //timeQuickSort(c, 6, 0); //Sort according to starting time of each course. //classroomDistribution(c, 6, classroom);//Direct strategy. timeQuickSort(c, 6, 1);//Sort according to finishing time of each course. classroomDistributionGreedy(c, 6, classroom);//Greedy strategy printCourseDistributed(classroom); return 0; }
相关文章推荐
- 图的点着色、区间着色问题及其应用(基于贪心思想的DFS回溯法求点着色问题和区间着色算法求解任务调度问题)
- [算法导论]练习16.1-4 活动教室分配(区间着色问题)
- 最少教室问题与区间图着色问题类似
- 区间调度问题详解
- 系列之五:最长公共子序列(LCS)问题(非连续子序列)的两种解法
- SGU 259 单机调度问题 +贪心 及此题解法的证明
- 带权区间调度问题,软件的期中复习
- 区间调度问题
- 求连续子数组最大和问题的两种解法_PHP实现
- 1877: 蛤玮打扫教室(区间覆盖问题)
- 贪心算法——区间调度问题
- 约瑟夫环问题的两种解法(详解)
- 装配线(工作站)问题的两种解法
- 【SQL】集合相等问题的两种解法
- uvaLive 2387 - Gene Assembly 最大区间调度问题
- 区间调度问题详解
- USACO 2005 Cleaning Shifts 带权区间调度、覆盖问题 单调栈优化dp
- 贪心-区间调度问题
- 算法系列之五:最长公共子序列(LCS)问题(非连续子序列)的两种解法
- 区间图着色问题(贪心算法)C++实现