基本上我是以递归的方式解决装配线调度问题,基于提供的公式here
可以从问题陈述中提取以下信息,以使其更简单:
两条装配线,1和2,每条装配线从1到n。
汽车底盘必须按顺序从1到n的所有工位通过(在两条装配线中的任何一条)。即如果它们不在一个移动距离,它就不能从站i跳到站j。
汽车底盘可以在同一条线上向前移动一个工作站,或在另一条线对角移动一个工作站。它会产生一个额外的费用ti,j从第i行移到j站。在同一行中移动不会产生任何费用。
第i行的第j站所花费的时间是ai,j。
Si,j表示第i行的站点j。
将问题分解为更小的子问题: 如果知道(i-1)阶乘,我们可以很容易地找到第i个阶乘。我们可以在这里应用类似的基础吗? 如果机箱离开站点Si所占的最短时间,j-1已知,则可以通过组合ai,j和ti,j来快速计算离开站点Si,j所需的最短时间。
T1(j)表示汽车底盘在装配线1上离开工位j所需的最短时间。
T2(j)表示汽车底盘在装配线2上离开工位j所需的最短时间。
基本情况: 只有当汽车底盘进入汽车厂时,进入时间ei才会出现。
离开第1行的第一站的时间由下式给出: T1(1)=第1行的进入时间+在站S1中花费的时间 T1(1)= e1 + a1,1 同样,在第2行离开第一站的时间由下式给出: T2(1)= e2 + a2,1
递归关系: 如果我们查看问题陈述,它很快就会归结为以下观察结果: 站S1,j处的汽车底盘可以来自站S1,j-1或站S2,j-1。
案例#1:其上一站是S1,j-1 离开S1,j的最短时间由下式给出: T1(j)=离开站S1所需的最短时间,j-1 +在站S1,j中花费的时间 T1(j)= T1(j-1)+ a1,j
案例#2:其上一站是S2,j-1 离开S1,j的最短时间由下式给出: T1(j)=离开S2站所需的最短时间,j-1 +更换装配线所产生的额外费用+在S1,j所花费的时间 T1(j)= T2(j-1)+ t2,j + a1,j
最小时间T1(j)由情况#1和#2中获得的最小值给出。 T1(j)= min((T1(j-1)+ a1,j),(T2(j-1)+ t2,j + a1,j)) 类似地,到达站S2的最小时间,j由下式给出: T2(j)= min((T2(j-1)+ a2,j),(T1(j-1)+ t1,j + a2,j))
汽车底盘出厂时所需的最短时间为: Tmin = min(离开车站Si所需的时间,n +退出汽车工厂所需的时间) Tmin = min(T1(n)+ x1,T2(n)+ x2)
动态编程版本很好,但是,我的递归版本中有一些隐藏的错误,有人可以帮我找出错误吗? 感谢。
package DP;
public class AssemblyLineScheduling {
public static void main(String[] args) {
int[][] a = {{4, 5, 3, 2},
{2, 10, 1, 4}};
int[][] t = {{0, 7, 4, 5},
{0, 9, 2, 8}};
int[] e = {10, 12};
int[] x = {18, 7};
System.out.println(carAssemblyDP(a, t, e, x));
System.out.println(carAssembly(a, t, e, x));
}
public static int carAssembly(int[][] a, int[][] t, int[] e, int[] x){
int n = a[0].length-1;
return Math.min(carAssemblyRec(a,t, e, x, n, 0) + x[0],
carAssemblyRec(a,t, e, x, n, 1) + x[1]);
}
public static int carAssemblyRec(int[][] a, int[][] t, int[] e, int[] x, int n, int line){
if(n == 0){
return e[line] + a[line][0];
}
int T0 = Math.min(carAssemblyRec(a, t, e, x, n-1, 0) + a[0][n]
, carAssemblyRec(a, t, e, x, n-1, 1) + t[1][n] + a[0][n]);
int T1 = Math.min(carAssemblyRec(a, t, e, x, n-1, 1) + a[1][n]
, carAssemblyRec(a, t, e, x, n-1, 0) + t[0][n] + a[1][n]);
return Math.min(T0, T1);
}
public static int carAssemblyDP(int[][] a, int[][] t, int[] e, int[] x){
int n = a[0].length;
int[] T1 = new int[n];
int[] T2 = new int[n];
T1[0] = e[0] + a[0][0];
T2[0] = e[1] + a[1][0];
for(int i=1; i<n; i++){
T1[i] = Math.min(T1[i-1]+a[0][i], T2[i-1]+t[1][i]+a[0][i]);
T2[i] = Math.min(T2[i-1]+a[1][i], T1[i-1]+t[0][i]+a[1][i]);
}
return Math.min(T1[n-1]+x[0], T2[n-1]+x[1]);
}
}
DP输出为35,这是正确的,但递归版本输出为29,这显然是错误的。
答案 0 :(得分:1)
我会回答我的问题。
public static int carAssemblyRec(int[][] a, int[][] t, int[] e, int[] x, int n, int line){
if(n == 0){
return e[line] + a[line][0];
}
int T0 = Integer.MAX_VALUE;
int T1 = Integer.MAX_VALUE;
if(line == 0){
T0 = Math.min(carAssemblyRec(a, t, e, x, n-1, 0) + a[0][n],
carAssemblyRec(a, t, e, x, n-1, 1) + t[1][n] + a[0][n]);
}else if(line == 1){
T1 = Math.min(carAssemblyRec(a, t, e, x, n-1, 1) + a[1][n],
carAssemblyRec(a, t, e, x, n-1, 0) + t[0][n] + a[1][n]);
}
return Math.min(T0, T1);
}