参考书籍:算法导论
l 问题描述:
共有两条装配线,每条有n个装配站,装配线i的第j个装配站用S[i,j]表示, 该站的装配时间用a[i,j]表示,一个汽车底盘进入装配线i,花费时间为e1,如果通过一条线的第j个装配站,这个底盘来到任意一条的第j+1个装配站,如果是相同的装配站,则没有额外的时间开销,如果移动到了另外一条装配线上,则花费时间t[i,j]。在离开一条装配线的第n个装配站后,完成汽车花费时间为xi离开工厂。待求解的问题是:应该分别在装配线1,2中选择哪些装配站,才能使汽车通过工厂的总时间最小。
l 装配站示意图:
l 分析过程:
动态规划的第一个步骤是描述最优子结构的特征。对于装配线调度问题,例:对于第一条装配线上的任意一个装配站S[1,j],到该装配站的最小时间可以看作为:从装配站S[1,j-1]出发到达S[1,j],或者通过S[2,j-1]出发加上额外时间t[2,j-1]到达S[1,j]。这里,S[1,j-1]和S[2,j-1]之前必定是利用了最短的时间到达了这两个装配站。这时就可以把问题转换为求出到达S[1,j-1]和S[2,j-1]的最短时间是多少,以此类推。
利用子问题的最优解来递归出一个最优解的值。用fi[j]表示一个底盘由起点到S[i,j]装配站的最短时间,最终通过工厂的总最小时间为f*;
f* = min(f1[n]+x1,f2[n]+x2);
对于f1[1]和f2[1]有:
f1[1] = e1 + a[1,1];
f2[1] = e2 + a[2,1];
对于f1[j]和f2[j],j>1,有:
f1[j] = min(f1[j-1] + a[1,j], f2[j-1] + t[2,j-1] + a[1,j])
f2[j] = min(f2[j-1] + a[2,j] ,f1[j-1] + t[1,j-1] + a[2,j])
以上两个式子反应了到达装配站S[i,j]的两种选择,取这两者较小者赋值给fi[j].
为了跟踪最优解的构造过程,特引入li[j];为装配线的编号,例如:l1[3]=2,含义是:到达装配站S[1,3]的上一条装配线是2号装配线。
以下为整个构造过程:
通过工厂的最快时间的路线:
l C++代码实现如下:
#include<iostream>
using namespace std;
int printStation(int *l1,int *l2,int resultI,int n){
cout<<"line"<<resultI<<" station "<<n<<endl;
int tempI= resultI;
for(inti=n-2;i>=0;i--){
if(tempI ==1){
cout<<"line"<<*(l1+i)<<" station "<<i+1<<endl;
tempI= *(l1+i);
}elseif(tempI == 2){
cout<<"line"<<*(l2+i)<<" station "<<i+1<<endl;
tempI= *(l2+i);
}
}
}
int getSelected(int *line_1,int *line_2 ,int *time_1,int *time_2){
int f1[6],f2[6];
int l1[5],l2[5];
f1[0] = *time_1 +*line_1 ;
f2[0] = *time_2 +*line_2 ;
int i=1;
for(;i<6;i++){
if((f1[i-1])<=(f2[i-1]+*(time_2 + i))){
f1[i]= f1[i-1] + *(line_1 + i);
l1[i-1]= 1;
}else{
f1[i]= f2[i-1]+ *(time_2 + i)+*(line_1 + i);
l1[i-1]= 2;
}
if((f2[i-1]+*(line_2+i))<=(f1[i-1]+*(time_1 +i) + *(line_2+i))){
f2[i]= f2[i-1]+*(line_2+i);
l2[i-1]= 2;
}else{
f2[i]= f1[i-1]+*(time_1 + i) + *(line_2+i);
l2[i-1]= 1;
}
}
int result;
int resultI;
if((f1[i-1] +*(time_1+i)) < (f2[i-1]+*(time_2 +i))){
result =f1[i-1] + *(time_1+i);
resultI = 1;
}else{
result =f2[i-1]+ *(time_2+i);
resultI = 2;
}
printStation(l1,l2,resultI,i);
return 1;
}
int main(){
int line_1[6] ={7,9,3,4,8,4};
int line_2[6] ={8,5,6,4,5,7};
int time_1[7] ={2,2,3,1,3,4,3};
int time_2[7] ={4,2,1,2,2,1,2};
getSelected(line_1,line_2,time_1,time_2);
return 1;
}