动态规划与贪心算法之课程安排问题

动态规划算法与贪心算法之课程安排问题

  1. 动态规划算法之课程安排
    问题:教务处给某一个教室安排课程,有很多老师都想来这个教室教授他们各自的课。假如第 i 位老师讲的第 Ai 门课程,课程开始时间 Si ,结束时间为 Fi 。那么教务处的老师就要利用这个时间如何安排课程,使得来这间教室上课的人数最多?
    举个例子:
    《动态规划与贪心算法之课程安排问题》
    最底下为时间轴,每条黑线代表一门课程。我们用 W 表示该课程有多少学生。我们看教务处安排最多有多少人来该教室上课。
    分析:课程太多我无从下手。看能不能分成子问题求解。先DandC,然后DP。我们把求解过程看出一系列决策过程,在每个步骤我们都要选一门课程。假装我们已经拿到了最优决策方案,我现在就想知道最优解中最后一个决策到底是什么?也就是 An 你是选了还是木有选?假如选择了,那 A8 肯定不能选。为啥,时间冲突啦。那剩下的问题就是从其他几门课选最优的。如下图所示:
    《动态规划与贪心算法之课程安排问题》
    也就是说我们选择了一门课程之后,问题规约成一个7门课程安排问题,这样我们继续往下把问题变小。此外我们刚才是选啦 A9 ,要是我们刚刚没选 A9 ,那怎么办呢?显然从其他8门课程选择,不管时间是否冲突。如下图所示:
    《动态规划与贪心算法之课程安排问题》
    这里插一句非常关键话:我们一开始把课程按结束时间排好序。
    现在我们就可以写出递归表达式了:
    OPT(n)=max OPT(pre(i))+WiOPT(i1) 此处,其中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[n].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[n].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(i1) 此处,其中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);
}

总结:动态规划算法和贪心算法都是用来求解优化问题。最优子结构性质二者都要用到,但是贪心算法还要用到贪心性质,这个不同问题,贪心性质不同。此外,每个贪心算法的背后几乎都有一个动态规划算法。上面的这两个问题都可用动态规划求解。但第一个问题却不能用贪心算法求解。动态规划算法需要在每一个决策步枚举所有的解空间中的解,而贪心算法不需要,依赖局部最优解来做决策。

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/mr_kktian/article/details/52783014
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞