DP34 流水线调度问题 Assembly Line Scheduling @geeksforgeeks

A car factory has two assembly lines, each with n stations. A station is denoted by Si,jwhere i is either 1 or 2 and indicates the assembly line the station is on, and j indicates the number of the station.The time taken per station is denoted by ai,j. Each station is dedicated to some sort of work like engine fitting, body fitting, painting and so on. So, a car chassis must pass through each of the n stations in order before exiting the factory. The parallel stations of the two assembly lines perform the same task. After it passes through station Si,j, it will continue to station Si,j+1unless it decides to transfer to the other line. Continuing on the same line incurs no extra cost, but transferring from line i at station j – 1 to station j on the other line takes time ti,j. Each assembly line takes an entry time eiand exit time xiwhich may be different for the two lines. Give an algorithm for computing the minimum time it will take to build a car chassis.

The below figure presents the problem in a clear picture:
Figure-1

The following information can be extracted from the problem statement to make it simpler:

  • Two assembly lines, 1 and 2, each with stations from 1 to n.
  • A car chassis must pass through all stations from 1 to n in order(in any of the two assembly lines). i.e. it cannot jump from station i to station j if they are not at one move distance.
  • The car chassis can move one station forward in the same line, or one station diagonally in the other line. It incurs an extra cost ti, j to move to station j from line i. No cost is incurred for movement in same line.
  • The time taken in station j on line i is ai, j.
  • Si, jrepresents a station j on line i.

Breaking the problem into smaller sub-problems:
We can easily find the ith factorial if (i-1)th factorial is known. Can we apply the similar funda here?
If the minimum time taken by the chassis to leave station Si, j-1is known, the minimum time taken to leave station Si, jcan be calculated quickly by combining ai, jand ti, j.

T1(j)indicates the minimum time taken by the car chassis to leave station j on assembly line 1.

T2(j)indicates the minimum time taken by the car chassis to leave station j on assembly line 2.

Base cases:
The entry time eicomes into picture only when the car chassis enters the car factory.

Time taken to leave first station in line 1 is given by:
T1(1) = Entry time in Line 1 + Time spent in station S1,1
T1(1) = e1+ a1,1
Similarly, time taken to leave first station in line 2 is given by:
T2(1) = e2+ a2,1

Recursive Relations:
If we look at the problem statement, it quickly boils down to the below observations:
The car chassis at station S1,jcan come either from station S1, j-1or station S2, j-1.

Case #1: Its previous station is S1, j-1
The minimum time to leave station S1,jis given by:
T1(j) = Minimum time taken to leave station S1, j-1+ Time spent in station S1, j
T1(j) = T1(j-1) + a1, j

Case #2: Its previous station is S2, j-1
The minimum time to leave station S1, j is given by:
T1(j) = Minimum time taken to leave station S2, j-1+ Extra cost incurred to change the assembly line + Time spent in station S1, j
T1(j) = T2(j-1) + t2, j+ a1, j

The minimum time T1(j) is given by the minimum of the two obtained in cases #1 and #2.
T1(j) = min((T1(j-1) + a1, j), (T2(j-1) + t2, j+ a1, j))
Similarly the minimum time to reach station S2, j is given by:
T2(j) = min((T2(j-1) + a2, j), (T1(j-1) + t1, j+ a2, j))

The total minimum time taken by the car chassis to come out of the factory is given by:
Tmin = min(Time taken to leave station Si,n+ Time taken to exit the car factory)
Tmin = min(T1(n) + x1, T2(n) + x2)

Why dynamic programming?
The above recursion exhibits overlapping sub-problems. There are two ways to reach station S1, j:

  1. From station S1, j-1
  2. From station S2, j-1

So, to find the minimum time to leave station S1, jthe minimum time to leave the previous two stations must be calculated(as explained in above recursion).
Similarly, there are two ways to reach station S2, j:

  1. From station S2, j-1
  2. From station S1, j-1

Please note that the minimum times to leave stations S1, j-1and S2, j-1have already been calculated.

So, we need two tables to store the partial results calculated for each station in an assembly line. The table will be filled in bottom-up fashion.

Note:
In this post, the word “leave” has been used in place of “reach” to avoid the confusion. Since the car chassis must spend a fixed time in each station, the word leave suits better.


流水线调度问题,DP的经典例子。到达某一装配点的货物既可以由本流水线过来,也可以由另一支流水线过来,取决于哪一个更合算。

以下例子答案:

Output:

35

Figure-2
The bold line shows the path covered by the car chassis for given input values.

Exercise:
Extend the above algorithm to print the path covered by the car chassis in the factory.


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 = Integer.MAX_VALUE;
		int T1 = Integer.MAX_VALUE;
		if(line == 0){		// 以下只适用于line0
			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){		// 以下只适用于line1
			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]);
	}
}


吐槽一下这题的递归,一开始我是这样写的:

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

结果和DP的不一样,于是在哪里想了半天哪里出问题,费了好大功夫,用debugger单步跟踪才发现原来是忘记加限制条件了!!!

正确写法应该是:

	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){		// 以下只适用于line0
			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){		// 以下只适用于line1
			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);
	}



http://www.geeksforgeeks.org/dynamic-programming-set-34-assembly-line-scheduling/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MATLAB中,可以使用符号计算工具箱(Symbolic Math Toolbox)来解决这个问题。以下是一个示例代码,假设已知六个点的坐标和它们之间的距离关系: ```matlab % 已知六个点的坐标 p1 = [x1; y1; z1]; p2 = [x2; y2; z2]; p3 = [x3; y3; z3]; p4 = [x4; y4; z4]; p5 = [x5; y5; z5]; p6 = [x6; y6; z6]; % 已知六个点之间的距离关系 d12 = norm(p1 - p2); d13 = norm(p1 - p3); d14 = norm(p1 - p4); d15 = norm(p1 - p5); d23 = norm(p2 - p3); d24 = norm(p2 - p4); d25 = norm(p2 - p5); d34 = norm(p3 - p4); d35 = norm(p3 - p5); d46 = norm(p4 - p6); d56 = norm(p5 - p6); % 计算任意六个点之间的距离关系 dp12 = norm(dp1 - dp2); dp13 = norm(dp1 - dp3); dp14 = norm(dp1 - dp4); dp15 = norm(dp1 - dp5); dp23 = norm(dp2 - dp3); dp24 = norm(dp2 - dp4); dp25 = norm(dp2 - dp5); dp34 = norm(dp3 - dp4); dp35 = norm(dp3 - dp5); dp46 = norm(dp4 - dp6); dp56 = norm(dp5 - dp6); % 建立方程组 eqns = [dp12 == d12, dp13 == d13, dp14 == d14, dp15 == d15, dp23 == d23, dp24 == d24, dp25 == d25, dp34 == d34, dp35 == d35, dp46 == d46, dp56 == d56]; % 求解方程组 [sol1, sol2, sol3, sol4, sol5, sol6] = solve(eqns, [dp1; dp2; dp3; dp4; dp5; dp6]); ``` 在上述代码中,我们首先定义了已知的六个点的坐标和它们之间的距离关系。然后,我们定义了一个符号变量`dp1, dp2, dp3, dp4, dp5, dp6`来表示任意六个点的坐标,然后建立了一个方程组,其中包含了任意六个点之间距离的关系和已知的六个点之间距离的关系。最后,使用solve函数求解这个方程组,得到任意六个点的坐标。 需要注意的是,该方法仅适用于已知的空间位置关系是基于距离的情况。对于其他类型的空间位置关系,可能需要使用不同的方法来判断任意六个点坐标是否符合该关系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值