动态规划算法入门

一、问题

       公司现在有8个任务,任务1-8的薪水分别是:5、1、8、4、6、3、2、4,有些任务之间是有时间冲突的,比如选了任务8就不能选任务6和7,而选了任务5就不能选任务1、2、3、4、6、7。如图,横轴代表时间,灰色矩形代表每个任务,矩形开始和结束的横坐标分别对应每个任务的开始和结束时间,红色数字代表薪水。比如任务1开始时间是1,结束时间是4,持续了(4-1)即3小时,薪水为5。现在的问题是,如何在0-11点之间,从这8个任务中选择时间互不冲突的若干个任务,使得得到的总薪水最大。

二、分析最优子结构、重叠子问题

用OPT(i)代表考虑第1至第i个任务时的最优解,比如OPT(5)代表考虑前5个任务的最优解,OPT(8)代表考虑前8个任务的最优解,考虑这个问题最关键的就是,分析每个任务选和不选的两种情况。现在由上图可知,选了任务8就不能选任务6和7,而任务8也可以不选,所以,当考虑OPT(8)时我们要考虑:

(1)如果选了任务8,任务6和7就不能选,那么只要再考虑前5个任务的最优解,即OPT(5);

(2)如果不选任务8,那只要考虑前7个任务的最优解,即OPT(7),就可以了;

(3)最后,我们比较上面两种情况得到的薪水,由薪水大小决定究竟选不选任务8

故OPT(8)=max{OPT(5)+4,OPT(7)},这里的4是指任务8的薪水,由上图可知是4

最后推出递归式:

扫描二维码关注公众号,回复: 2695427 查看本文章

上式,OPT(i)代表考虑前i个任务的最优解(1≤i≤8),Vi代表第i个任务的薪水,prev(i)是一个数组,标记如果选择了第i个任务,则剩余只要考虑前几个任务就可以了,比如prev(8)=5,如果选了第8个任务,只要考虑前5个就可以了;prev(6)=2,如果选了第6个任务,只要考虑前2个就可以了;

根据这个问题,我们可以得到Vi表:

V1 V2 V3 V4 V5 V6 V7 V8
5 1 8 4 6 3 2 4

prev(i)表:

prev(1) prev(2) prev(3) prev(4) prev(5) prev(6) prev(7) prev(8)
0 0 0 1 0 2 3 5

最终由递推式计算得到OPT(i)表,注意初始时OPT(0)=0,而OPT(8)就是我们要的最终解:

OPT(0) OPT(1) OPT(2) OPT(3) OPT(4) OPT(5) OPT(6) OPT(7) OPT(8)
0 5 5 8 9 9 9 10 13

上表中,比如OPT(3)代表如果只考虑前3个任务能得到的最大薪水,由于

OPT(3)=max{OPT(0)+8,OPT(2)}

而OPT(0)+8=8,OPT(2)已经计算好,为5,那么OPT(0)+8 > OPT(2),(注:

OPT(2)是怎么来的: 计算OPT(2)=max{OPT(0)+1,OPT(1)} 得到 OPT(0)+1 < OPT(1)

由于OPT(1)大所以要考虑OPT(1)是怎么来的: OPT(1)=max{OPT(0)+5,OPT(0)}=OPT(0)+5=5

可见如果只考虑前3个任务,我们选做任务集合为{3}时,就能得到最大薪水,为8

其他以此类推。

所以,最终能得到的最大薪水为OPT(8)=13。

猜你喜欢

转载自blog.csdn.net/qq_32919451/article/details/81142244