上学的时候有一道题目一直困扰着我,那就是厨师摆盘子问题,问题的描述是这样的:
厨师的所有盘子都放在一个架子上,每天工作结束他都要将盘子按照从小到大的顺序排好,问题是架子不太稳,如果一次拿出一个或几个盘子,架子可能要倒掉,所以他必须只能从一边翻动盘子,由于他只有两只手,所以只能用两只手将拿起的盘子一起翻转。问题是当给出一个杂乱的盘子序列时,如何以最小的翻转次数将其排序。
当时用穷举的方法解决了这个问题,但是看到很多资料都说此类最优解的问题还可以用动态规划法解决,但是我一直没有找到分解最优子问题的方法,所以只好放弃了。前一段时间看《编程之美》,其中“一摞烙饼问题”那一章提到的一摞烙饼问题其实和厨师摆盘子是一回事儿,文中提到了可用动态规划法解决,但是没有给出解法,这又勾起了我的念头,我又翻出了《算法导论》,并动用了Google,百度和雅虎,但是仍然没有找到用动态规划法的解法,倒是看到一些关于这个问题无法用动态规划法解决的讨论。虽然没有找到答案,但是把以前的老代码翻出来了,看到了当时解决“装配线(工作站)问题”的代码,当时用动态规划法和穷举法两种方法解决了这个问题,现在就晒晒代码,先看看“装配线(工作站)问题”的描述:
Colonel汽车公司在有两条装配线的工厂内生产汽车,一个汽车底盘在进入每一条装配线后,在每个装配站会在汽车底盘上安装不同的部件,最后完成的汽车从装配线的末端离开。如图1.所示:
每一条装配线上有n个装配站,编号为j=1,2,...,n,将装配线i(i为1或2)的第j个装配站表示为S(i,j)。装配线1的第j个站S(1,j)和装配线2的第j个站S(2,j)执行相同的功能。然而这些装配站是在不同的时间建造的,并且采用了不同的技术,因此,每个站上完成装配所需要的时间也不相同,即使是在两条装配线相同位置的装配站也是这样。把每个装配站上所需要的装配时间记为a(i,j),并且,底盘进入装配线i需要的时间为e(i),离开装配线i需要的时间是x(i)。正常情况下,底盘从一条装配线的上一个站移到下一个站所花费的时间可以忽略,但是偶尔也会将未完成的底盘从一条装配线的一个站移到另一条装配线的下一站,比如遇到紧急订单的时候。假设将已经通过装配站S(i,j)的底盘从装配线i移走所花费的时间为t(i,j),现在的问题是要确定在装配线1内选择哪些站以及在装配线2内选择哪些站,以使汽车通过工厂的总时间最小,如图2.所示,最快的时间是选择装配线1的1,3和6装配站以及装配线2的2,4和5装配站。
按照《算法导论》书中的讨论,我首先给出了使用动态规划法的算法。动态规划的第一步是描述最优解的结构特征,也就是要先定义什么是最优解。对于装配线问题
厨师的所有盘子都放在一个架子上,每天工作结束他都要将盘子按照从小到大的顺序排好,问题是架子不太稳,如果一次拿出一个或几个盘子,架子可能要倒掉,所以他必须只能从一边翻动盘子,由于他只有两只手,所以只能用两只手将拿起的盘子一起翻转。问题是当给出一个杂乱的盘子序列时,如何以最小的翻转次数将其排序。
当时用穷举的方法解决了这个问题,但是看到很多资料都说此类最优解的问题还可以用动态规划法解决,但是我一直没有找到分解最优子问题的方法,所以只好放弃了。前一段时间看《编程之美》,其中“一摞烙饼问题”那一章提到的一摞烙饼问题其实和厨师摆盘子是一回事儿,文中提到了可用动态规划法解决,但是没有给出解法,这又勾起了我的念头,我又翻出了《算法导论》,并动用了Google,百度和雅虎,但是仍然没有找到用动态规划法的解法,倒是看到一些关于这个问题无法用动态规划法解决的讨论。虽然没有找到答案,但是把以前的老代码翻出来了,看到了当时解决“装配线(工作站)问题”的代码,当时用动态规划法和穷举法两种方法解决了这个问题,现在就晒晒代码,先看看“装配线(工作站)问题”的描述:
Colonel汽车公司在有两条装配线的工厂内生产汽车,一个汽车底盘在进入每一条装配线后,在每个装配站会在汽车底盘上安装不同的部件,最后完成的汽车从装配线的末端离开。如图1.所示:

图1. 装配线示意图
每一条装配线上有n个装配站,编号为j=1,2,...,n,将装配线i(i为1或2)的第j个装配站表示为S(i,j)。装配线1的第j个站S(1,j)和装配线2的第j个站S(2,j)执行相同的功能。然而这些装配站是在不同的时间建造的,并且采用了不同的技术,因此,每个站上完成装配所需要的时间也不相同,即使是在两条装配线相同位置的装配站也是这样。把每个装配站上所需要的装配时间记为a(i,j),并且,底盘进入装配线i需要的时间为e(i),离开装配线i需要的时间是x(i)。正常情况下,底盘从一条装配线的上一个站移到下一个站所花费的时间可以忽略,但是偶尔也会将未完成的底盘从一条装配线的一个站移到另一条装配线的下一站,比如遇到紧急订单的时候。假设将已经通过装配站S(i,j)的底盘从装配线i移走所花费的时间为t(i,j),现在的问题是要确定在装配线1内选择哪些站以及在装配线2内选择哪些站,以使汽车通过工厂的总时间最小,如图2.所示,最快的时间是选择装配线1的1,3和6装配站以及装配线2的2,4和5装配站。

图2. 装配线的一个最快时间路线
按照《算法导论》书中的讨论,我首先给出了使用动态规划法的算法。动态规划的第一步是描述最优解的结构特征,也就是要先定义什么是最优解。对于装配线问题