动态规划——装配线调度

来源:互联网 发布:mysql数据库巡检报告 编辑:程序博客网 时间:2024/05/16 01:09

问题描述

A manufacturing problem to find the fastest way through a factory. There are two assembly lines, each withn stations; thejth station on line i is denotedSi,j and the assembly time at that station isai,j. An automobile chassis enters the factory, and goes onto linei (where i = 1 or 2), taking ei time. After going through thejth station on a line, the chassis goes on to the (j + 1)st station on either line. There is no transfer cost if it stays on the same line, but it takes timeti,j to transfer to the other line after stationSi,j. After exiting thenth station on a line, it takesxi time for the completed auto to exit the factory. The problem is to determine which stations to choose from line 1 and which to choose from line 2 in order to minimize the total time through the factory for one auto.


动态规划的解题步骤有四步:


这道题目的做法也是按照这四步来做,一步一步来。

第一步:通过工厂最快路线的结构

其中到达每一条装配线的第一个装配站的最快时间是可以一开始就确定的。然后要求通过n个装配站后的最快路线,那么就是求通过第n个装配站时候的最短时间,要求通过第n个装配站时候的最短时间,那么就只需要通过通过第n-1个装配站时的最短时间来求。因此,通过某一条装配线的装配站的最短时间就是下面两条线中的一条:

确定好最优解的结构后,接下来就是第二步:递归地定义最优解的值

在这之前先说明要用到的一些符号的定义:

进入每条装配线的时间存在数组e[]中
出每条装配线的时间存放在数组x[]中
每条装配线的每个装配站的时间存放在数组a[2][n]中,a[1][4]就代表第2条装配线的第5个装配站。
从一条装配线的某一个装配站,到另一条装配线的下一个装配站的时间,存放在数组t[2][n]中,
例如,t[0][4]就代表从第一条装配线的第五个装配站转移到第二条装配线的第六个装配站的时间。
计算最短时间的过程中,用数组f[2][n]保存过程的中间解。例如,f[1][3]就保存了到达第二条
装配线的第四个装配站的最短时间。然后用min_f保存最终的结果,也就是最短的生产时间。
为了输出整条最短时间的生产装配站序列,再设一个数组L[2][n],其中L[1][5]就表示到达第二条装配
线的第六个装配站的前一个装配站,也就是第五个装配站是属于哪一条装配线的,是1还是2.然后
fin_l保存最终生成完成时,是从哪一条装配线出来的。

最终我们要求的结果就是min_f(就是下面图中的f*),经过工厂n个装配站的最短时间

公式表达的很清晰,这个公式就是用上面提到的最优解结构的求法定义出来的。

根据递归的定义以及上面的内容,也可以得出要求出到达每一个装配站的最优时间的递归公式


这样就可以求出最终的min_f了,也就是第三步的计算最优解的值就出来了。因为还有第四步,就是构造最优解,在这道题目中,就是要构造出这条时间花费最小的路线。为了可以构造出这条路线,还要记录下到达每一个装配站时,上一个装配站是属于哪一条装配线的,也就是上面的数组L[2][n]的定义。

下面是代码,数据是按照下面这张图输入的


#include <iostream>#include <stack>using namespace std;//输出最短路径的组成void Print_Station(int l[2][6],int fin_l,int n){stack<int> s;int i=fin_l;s.push(i);for(int j=n-1;j>=1;j--){i=l[i-1][j];s.push(i);}for(j=1;j<=n;j++){cout<<"Line "<<s.top()<<" ,Station "<<j<<endl;s.pop();}}//计算时间最短的路径花费时间int Fastest_Way( int a[][6],int t[][6],int e[],int x[], int n,int f[][6],int l[][6] ){int fin_l,min_f;f[0][0]=e[0]+a[0][0];f[1][0]=e[1]+a[1][0];for(int j=1;j<n;j++){if( (f[0][j-1]+a[0][j]) <= (f[1][j-1]+t[1][j-1]+a[0][j]) ){f[0][j]=f[0][j-1]+a[0][j];l[0][j]=1;}else{f[0][j]=f[1][j-1]+t[1][j-1]+a[0][j];l[0][j]=2;}if( (f[1][j-1]+a[1][j]) <= (f[0][j-1]+t[0][j-1]+a[1][j]) ){f[1][j]=f[1][j-1]+a[1][j];l[1][j]=2;}else{f[1][j]=f[0][j-1]+t[0][j-1]+a[1][j];l[1][j]=1;}}if( (f[0][n-1]+x[0]) <= (f[1][n-1]+x[1]) ){min_f=f[0][n-1]+x[0];fin_l=1;}else{min_f=f[1][n-1]+x[1];fin_l=2;}Print_Station(l,fin_l,n);return min_f;}int main(){int a[2][6]={{7,9,3,4,8,4},{8,5,6,4,5,7}},t[2][6]={{2,3,1,3,4,0},{2,1,2,2,1,0}},e[2]={2,4},x[2]={3,2},f[2][6],l[2][6],min_f;cout<<"最短时间的路径如下:"<<endl;min_f=Fastest_Way(a,t,e,x,6,f,l);cout<<"最短的时间为:"<<min_f<<endl;return 0;}

输出结果:

最短时间的路径如下:Line 1 ,Station 1Line 2 ,Station 2Line 1 ,Station 3Line 2 ,Station 4Line 2 ,Station 5Line 1 ,Station 6最短的时间为:38Press any key to continue

结果就是上图中的黑色路径,这是第一篇关于DP的日志,所以写的较为详细。


原创粉丝点击