动态规划与贪心算法之课程安排问题
2016-10-10 23:14
453 查看
动态规划算法与贪心算法之课程安排问题
动态规划算法之课程安排问题:教务处给某一个教室安排课程,有很多老师都想来这个教室教授他们各自的课。假如第i位老师讲的第Ai门课程,课程开始时间Si,结束时间为Fi。那么教务处的老师就要利用这个时间如何安排课程,使得来这间教室上课的人数最多?
举个例子:
最底下为时间轴,每条黑线代表一门课程。我们用W表示该课程有多少学生。我们看教务处安排最多有多少人来该教室上课。
分析:课程太多我无从下手。看能不能分成子问题求解。先DandC,然后DP。我们把求解过程看出一系列决策过程,在每个步骤我们都要选一门课程。假装我们已经拿到了最优决策方案,我现在就想知道最优解中最后一个决策到底是什么?也就是An 你是选了还是木有选?假如选择了,那A8 肯定不能选。为啥,时间冲突啦。那剩下的问题就是从其他几门课选最优的。如下图所示:
也就是说我们选择了一门课程之后,问题规约成一个7门课程安排问题,这样我们继续往下把问题变小。此外我们刚才是选啦A9,要是我们刚刚没选A9,那怎么办呢?显然从其他8门课程选择,不管时间是否冲突。如下图所示:
这里插一句非常关键话:我们一开始把课程按结束时间排好序。
现在我们就可以写出递归表达式了:
OPT(n)=max⎧⎩⎨ OPT(pre(i))+WiOPT(i−1)此处,其中pre(i)是表示第i门课程开始时已经结束的课程。
具体实现过程如下:
#include<stdio.h> struct course{ float start; float end; int w; }Course[9]; void init_course_information(){ Course[0].start =8;Course[0].end=9;Course[0].w=1; Course[1].start=8;Course[1].end=9.30;Course[1].w= 5; Course[2].start =9.20;Course[2].end =10;Course[2].w=4; Course[3].start =9.40;Course[3].end =10.30;Course[3].w=2; Course[4].start =11.00;Course[4].end =12.30;Course[4].w=3; Course[5].start =8;Course[5].end =12.50;Course[5].w=2; Course[6].start =11.30;Course[6].end =13.00;Course[6].w=1; Course[7].start =15;Course[7].end =16;Course[7].w=3; Course[8].start =14;Course[8].end =17;Course[8].w=5; } int max(int a,int b){ return a>b?a:b; } int pre(int n){//求课程n开始时结束的所有课程 float current_start; int result=0,i; current_start=Course .start; for(i=0;i<8;i++){ if(Course[i].end>current_start){ result=i-1; break; } } return result; } int Scheduling_DP(int n){ int m=0; if(n<0) return 0; else if(n==0){ return Course[0].w; } else{ m=max( (Scheduling_DP(pre(n))+Course .w ), Scheduling_DP(n-1) ); return m; } } void main(){ int i,result; int n=9;//课程数量 init_course_information(); printf(" 开始时间 结束时间 上课人数:\n"); for(i=0;i<9;i++) printf("课程%d:%6.2f%8.2f%9d\n", i, Course[i]. start,Course[i]. end,Course[i].w); result=Scheduling_DP(n-1); printf("最多上课人数=%d\n",result); }
运行结果如下:
2. 贪心算法之课程安排问题:
问题:现在我们假设每个课程的人数都为1。我们的任务还是和原来一样,选择一些不冲突的课程,让来该教室上课的学生人数最多,怎么办?当然上面的动态算法我们可以继续使用。但DP来解决这个问题就感觉有点慢了。为啥?还有更快的算法?问题如下图所示:
分析: 我们来审视这个问题。原来的性质依然存在。而且还多了个性质,那就是贪心选择的性质。它又是什么呢?回到问题本身,可以这么描述,假如课程Ai 下课最早,那么它肯定会出现在最优解。首先我们选最早下课的课程A1,接下来的问题就是在蓝色的方框里面选最优解就行,如此规约。
这个时候,我们写出递归表达式如下:
OPT(n)=max⎧⎩⎨ OPT(pre(i))+WiOPT(i−1)此处,其中pre(i)是表示第i门课程开始时已经结束的课程。
具体实现过程如下:
#include<stdio.h> struct course{ float start; float end; int w; }Course[9]; void init_Course_information(){ Course[0].start =8;Course[0].end =9;Course[0].w=1; Course[1].start =8;Course[1].end =9.30;Course[1].w=1; Course[2].start =9.20;Course[2].end =10;Course[2].w=1; Course[3].start =9.40;Course[3].end =10.30;Course[3].w=1; Course[4].start =11.00;Course[4].end =12.30;Course[4].w=1; Course[5].start =8;Course[5].end =12.50;Course[5].w=1; Course[6].start =11.30;Course[6].end =13.00;Course[6].w=1; Course[7].start =15;Course[7].end =16;Course[7].w=1; Course[8].start =14;Course[8].end =17;Course[8].w=1; } int Scheduling_Greedy(int n){ int previous_finish_time=0; int num=0; int i; for(i=0;i<9;i++){ if(Course[i].start>previous_finish_time){ previous_finish_time=Course[i].end; num+=1; } } return num; } void main(){ int i,result; int n=9;//课程数量 init_Course_information(); printf(" 开始时间 结束时间 上课人数:\n"); for(i=0;i<9;i++){ printf("程%d:%6.2f%8.2f%9d\n",i,Course[i].start,Course[i].end,Course[i].w); } result=Scheduling_Greedy(n-1); printf("最多上课人数=%d\n",result); }
总结:动态规划算法和贪心算法都是用来求解优化问题。最优子结构性质二者都要用到,但是贪心算法还要用到贪心性质,这个不同问题,贪心性质不同。此外,每个贪心算法的背后几乎都有一个动态规划算法。上面的这两个问题都可用动态规划求解。但第一个问题却不能用贪心算法求解。动态规划算法需要在每一个决策步枚举所有的解空间中的解,而贪心算法不需要,依赖局部最优解来做决策。
相关文章推荐
- 动态规划经典算法之矩阵连乘问题源代码
- 算法之动态规划——编辑距离问题
- 【算法导论】贪心算法之活动安排问题
- (基于Java)算法之贪心算法——活动安排问题
- (基于Java)算法之动态规划——矩阵连乘问题
- 贪心算法 安排活动的问题 最大限度的利用有限资源
- 流水线调度问题实现(动态规划基础---------问题取自算法导论)
- 动态规划解机器调度问题——算法解题报告
- 动态规划解乘法表问题——算法解题报告
- (基于Java)算法之动态规划——0-1背包问题
- 活动安排问题之贪心算法
- 算法之动态规划 之 子问题重叠和最优子结构
- 算法导论学习笔记(十三):动态规划(三):01背包问题
- 【算法导论】贪心算法之活动安排问题
- 饮料问题;动态规划;贪心没看懂;
- 算法:动态规划解 0-1 背包问题
- 贪心算法——活动安排问题
- 贪心算法——NY 14 会场安排问题
- (基于Java)算法之动态规划——矩阵连乘问题
- 算法夜谈の动态规划问题