装配线调度

问题:一个工厂有两条装配线a1, a2,每条装配线有n个装配站,每个编号对等的装配站功能相同。机器只要依次通过编号为1,2,...,n的装配站即可加工完成。已知两条装配线各个装配站装配所需的时间即a1,1,a1,2,...,a1,n,  a2,1,a2,2,...,a2,n, 进入装配线所需时间e1,e2,离开装配线所需时间x1,x2。有时候为了加快装配进度,可以将部分完成的机器从一条装配线移到另一条装配线,所需时间分别为t1,1,t1,2,...,t1,n-1,  t2,1,t2,2,...,t2,n-1. 求机器制造所需的最短时间。

 

算法基本思路:

1.计算最优解即最短时间;

要求最短时间,可以看作求到达装配s1,n, s2,n的最短时间。要到达s1,n,有两种可能。

(1)从s1,n-1直接到s1,n;

(2)从s2,n-1经过t2,n-1到达s1,n

对于s2,n,也是类似情况。

不难看出,几乎对于所有站点都存在这个性质(起始站点除外)。满足最优子结构,和重叠子问题(对等编号的站点对前一站点的最优时间重复使用),可用动态规划法。

 

设f[1][i]表示到达装配线1上 i 号站点所需的最短时间,f[2][i]表示到达装配线2上 i 号站点所需的最短时间。

f[1][1]初始化为e[1] + a[1][1],f[2][1]初始化为e[2] + a[2][1]。则有,

f[1][i] = min{f[1][i-1] + a[1][i], f[2][i-1] + t[2][i-1] + a[1][i]}, (2<= i <= n)

f[2][i] = min{f[2][i-1] + a[2][i], f[1][i-1] + t[1][i-1] + a[2][i]}, (2<= i <= n)

此时易得最小时间 t = min{f[1][n] + x[1], f[2][n] + x[2]}。

 

2.构造获得最短时间的路线。

在计算最短时间的基础上,多开一个记录表 l[1][i] 表示 到达装配线1上 i 号站点的前一个站点, l[2][i] 表示 到达装配线2上 i 号站点的前一个站点。

从最后一个站点逆推可得整条路线。

 

public class AssemblyLineScheduling{

    public static String fastestWay(int[][] a, int[][] t, int[] e, int[] x){
        /*
        a means the cost time of assembly station
        t means the transform time betweeen different line
        e means the time of enter assembly line
        x means the time of exit assembly line
        return the cost time of the fastest way
        */
        int n = a[0].length;
        int[][] f = new int[2][n];
        int[][] l = new int[2][n-1];
        //init
        f[0][0] = a[0][0] + e[0];
        f[1][0] = a[1][0] + e[1];
        //dynamic programming
        for(int i = 1; i < n; i ++){
            if(f[0][i-1] + a[0][i] < f[1][i-1] + t[1][i-1] + a[0][i]){
                f[0][i] = f[0][i-1] + a[0][i];
                l[0][i-1] = 0;
            }
            else{
                f[0][i] = f[1][i-1] + t[1][i-1] + a[0][i];
                l[0][i-1] = 1;
            }
            if(f[0][i-1] + t[0][i-1] + a[1][i] < f[1][i-1] + a[1][i]){
                f[1][i] = f[0][i-1] + t[0][i-1] + a[1][i];
                l[1][i-1] = 0;
            }
            else{
                f[1][i] = f[1][i-1] + a[1][i];
                l[1][i-1] = 1;
            }
        }
        int r;
        int p;
        //build the path
        if(f[0][n-1] + x[0] < f[1][n-1] + x[1]){
            r = f[0][n-1] + x[0];
            p = 0;
        }
        else{
            r = f[1][n-1] + x[1];
            p = 1;
        }
        String result = "line " + p + ", station " + (n-1) + "\n" + r;
        for(int i = n-2; i >= 0; i --){
            result = "line " + l[p][i] + ", station " + i + "\n" + result;
            p = l[p][i];
        }
        return result;
    }

    public static void main(String[] args) {
        //Unit Testing
        int[][] a = {{7, 9, 3, 4, 8, 4}, {8, 5, 6, 4, 5, 7}};
        int[][] t = {{2, 3, 1, 3, 4}, {2, 1, 2, 2, 1}};
        int[] e = {2, 4};
        int[] x = {3, 2};
        System.out.println(fastestWay(a, t, e, x));
    }
    
}
Java

 

posted @ 2013-12-05 08:49  7hat  阅读(344)  评论(0编辑  收藏  举报