装配线调度递归解决方案错误

时间:2013-12-29 21:14:51

标签: java algorithm recursion dynamic-programming

基本上我是以递归的方式解决装配线调度问题,基于提供的公式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,这显然是错误的。

1 个答案:

答案 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);  
}