Assembly Line Scheduling (original) (raw)

A car factory has **two assembly lines, each containing **n stations. Every station performs a specific task such as engine fitting, body fitting, painting, etc. The stations at the same position on both assembly lines perform the **same type of task.

You are given:

2056958061

A car chassis must pass through **all n stations in order, starting from either assembly line, and may switch between lines at any station while incurring the corresponding transfer time.

Determine the **minimum total time required to manufacture the car chassis.

**Example:

**Input: a[2][] =[[4, 5, 3, 2], [2, 10, 1, 4]], T[2][] = [[0,7, 4, 5], [0,9, 2, 8]],
e[2] = [10,12], x[2] = [18,7]
**Output: 35
**Explanation: According to the TC, this would be the following diagram. The bold line shows the path covered by the car chassis for given input values. So the minimum time taken by the car is 35.

2056958060

Table of Content

[Naive Approach] Using Recursion Approach - O(2 ^ n) Time and O(n) Space

We have two choices: either continue on the same assembly line or switch to the other line by paying the transfer cost. The recursive function explores both possibilities for each station and calculates the minimum total time needed to reach the end. The base case occurs at the last station, where we simply add the exit time of the current assembly line. Finally, we take the minimum time obtained by starting from either of the two assembly lines.

#include #include #include using namespace std;

// Recursive function int solve(vector<vector> &a, vector<vector> &T, int currentLine, int currentStation, vector &x, int n) { // Base Case: // If we are at the last station, // add exit time of the current line if (currentStation == n - 1) { return x[currentLine]; }

// Option 1:
// Continue on the same assembly line
int sameLine = solve(a, T, currentLine, currentStation + 1, x, n) + a[currentLine][currentStation + 1];

// Option 2:
// Switch to the other assembly line
int changeLine = solve(a, T, !currentLine, currentStation + 1, x, n) +
                 a[!currentLine][currentStation + 1] + T[currentLine][currentStation + 1];

// Return minimum of both choices
return min(sameLine, changeLine);

}

// Function to find minimum assembly time int carAssembly(vector<vector> &a, vector<vector> &T, vector &e, vector &x) { int n = a[0].size();

// Start from Assembly Line 0
int line0 = solve(a, T, 0, 0, x, n) + e[0] + a[0][0];

// Start from Assembly Line 1
int line1 = solve(a, T, 1, 0, x, n) + e[1] + a[1][0];

// Return overall minimum time
return min(line0, line1);

}

int main() { vector<vector> a = {{4, 5, 3, 2}, {2, 10, 1, 4}};

vector<vector<int>> T = {{0, 7, 4, 5}, {0, 9, 2, 8}};

vector<int> e = {10, 12};
vector<int> x = {18, 7};

int ans = carAssembly(a, T, e, x);

cout << ans << endl;

return 0;

}

Java

import java.util.*;

// Main Class public class GFG {

// Recursive function
static int solve(int[][] a, int[][] T, int currentLine,
                 int currentStation, int[] x, int n)
{
    // Base Case:
    // If we are at the last station
    if (currentStation == n - 1) {
        return x[currentLine];
    }

    // Option 1:
    // Continue on same line
    int sameLine = solve(a, T, currentLine,
                         currentStation + 1, x, n)
                   + a[currentLine][currentStation + 1];

    // Option 2:
    // Switch to another line
    int changeLine
        = solve(a, T, 1 - currentLine,
                currentStation + 1, x, n)
          + a[1 - currentLine][currentStation + 1]
          + T[currentLine][currentStation + 1];

    // Return minimum
    return Math.min(sameLine, changeLine);
}

// Function to find minimum assembly time
public static int carAssembly(int n, int[][] a,
                              int[][] T, int[] e,
                              int[] x)
{
    // Start from line 0
    int line0 = solve(a, T, 0, 0, x, n) + e[0] + a[0][0];

    // Start from line 1
    int line1 = solve(a, T, 1, 0, x, n) + e[1] + a[1][0];

    // Return minimum time
    return Math.min(line0, line1);
}

public static void main(String[] args)
{
    int n = 4;

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

    int ans = carAssembly(n, a, T, e, x);

    System.out.println(ans);
}

}

Python

Recursive function

def solve(a, T, currentLine, currentStation, x, n):

# Base Case:
# If we are at the last station
if currentStation == n - 1:
    return x[currentLine]

# Option 1:
# Continue on same line
sameLine = solve(a, T, currentLine, currentStation + 1,
                 x, n) + a[currentLine][currentStation + 1]

# Option 2:
# Switch to another line
changeLine = solve(a, T, 1 - currentLine, currentStation + 1, x, n) + \
    a[1 - currentLine][currentStation + 1] + \
    T[currentLine][currentStation + 1]

# Return minimum
return min(sameLine, changeLine)

Function to find minimum assembly time

def carAssembly(n, a, T, e, x):

# Start from line 0
line0 = (solve(a, T, 0, 0, x, n) + e[0] + a[0][0])

# Start from line 1
line1 = (solve(a, T, 1, 0, x, n) + e[1] + a[1][0])

# Return minimum time
return min(line0, line1)

Driver Code

if name == "main": n = 4 a = [[4, 5, 3, 2], [2, 10, 1, 4]]

T = [[0, 7, 4, 5], [0, 9, 2, 8]]

e = [10, 12]
x = [18, 7]

ans = carAssembly(n, a, T, e, x)

print(ans)

C#

using System;

class GFG {

// Recursive function
static int Solve(int[][] a, int[][] T, int currentLine,
                 int currentStation, int[] x, int n)
{
    // Base Case:
    // If we are at the last station
    if (currentStation == n - 1) {
        return x[currentLine];
    }

    // Option 1:
    // Continue on same line
    int sameLine = Solve(a, T, currentLine,
                         currentStation + 1, x, n)
                   + a[currentLine][currentStation + 1];

    // Option 2:
    // Switch to another line
    int changeLine
        = Solve(a, T, 1 - currentLine,
                currentStation + 1, x, n)
          + a[1 - currentLine][currentStation + 1]
          + T[currentLine][currentStation + 1];

    // Return minimum
    return Math.Min(sameLine, changeLine);
}

// Function to find minimum assembly time
static int carAssembly(int[][] a, int[][] T, int[] e,
                       int[] x)
{
    int n = a[0].Length;

    // Start from line 0
    int line0 = Solve(a, T, 0, 0, x, n) + e[0] + a[0][0];

    // Start from line 1
    int line1 = Solve(a, T, 1, 0, x, n) + e[1] + a[1][0];

    // Return minimum time
    return Math.Min(line0, line1);
}
static void Main()
{
    int[][] a
        = new int[][] { new int[] { 4, 5, 3, 2 },
                        new int[] { 2, 10, 1, 4 } };

    int[][] T
        = new int[][] { new int[] { 0, 7, 4, 5 },
                        new int[] { 0, 9, 2, 8 } };

    int[] e = { 10, 12 };
    int[] x = { 18, 7 };

    int ans = carAssembly(a, T, e, x);

    Console.WriteLine(ans);
}

}

JavaScript

// Recursive function function solve(a, T, currentLine, currentStation, x, n) { // Base Case: // If we are at the last station if (currentStation === n - 1) { return x[currentLine]; }

// Option 1:
// Continue on same line
let sameLine
    = solve(a, T, currentLine, currentStation + 1, x, n)
      + a[currentLine][currentStation + 1];

// Option 2:
// Switch to another line
let changeLine
    = solve(a, T, 1 - currentLine, currentStation + 1, x, n)
      + a[1 - currentLine][currentStation + 1]
      + T[currentLine][currentStation + 1];

// Return minimum
return Math.min(sameLine, changeLine);

}

// Function to find minimum assembly time function carAssembly(a, T, e, x) { let n = a[0].length;

// Start from line 0
let line0 = solve(a, T, 0, 0, x, n) + e[0] + a[0][0];

// Start from line 1
let line1 = solve(a, T, 1, 0, x, n) + e[1] + a[1][0];

// Return minimum time
return Math.min(line0, line1);

}

// Driver Code

let a = [ [ 4, 5, 3, 2 ], [ 2, 10, 1, 4 ] ];

let T = [ [ 0, 7, 4, 5 ], [ 0, 9, 2, 8 ] ];

let e = [ 10, 12 ]; let x = [ 18, 7 ];

let ans = carAssembly(a, T, e, x);

console.log(ans);

`

Consider the following example: line = 2, stations = 3

s111

Explanation using recursive tree(highlighted states showing overlapping sub-problems)

[Expected Approach - 1] Using Memoization(DP) - O(n) Time and O(n) Space

The above recursive solution contains overlapping subproblems because the same state gets solved multiple times. We use **Memoization (Dynamic Programming) and store the result of each state in a dp array. Whenever the same state is encountered again, we directly return the stored value instead of recalculating it.

#include #include #include using namespace std;

// Recursive + Memoization function int solve(vector<vector> &a, vector<vector> &T, int currentLine, int currentStation, vector &x, int n, vector<vector> &dp) { // Base Case: // If we are at the last station, // add exit time of current line if (currentStation == n - 1) { return x[currentLine]; }

// If already computed
if (dp[currentLine][currentStation] != -1)
{
    return dp[currentLine][currentStation];
}

// Option 1:
// Continue on same assembly line
int sameLine =
    solve(a, T, currentLine, currentStation + 1, x, n, dp) + a[currentLine][currentStation + 1];

// Option 2:
// Switch to the other assembly line
int changeLine = solve(a, T, !currentLine, currentStation + 1, x, n, dp) +
                 a[!currentLine][currentStation + 1] + T[currentLine][currentStation + 1];

// Store and return minimum answer
return dp[currentLine][currentStation] = min(sameLine, changeLine);

}

// Function to find minimum assembly time int carAssembly(vector<vector> &a, vector<vector> &T, vector &e, vector &x) { int n = a[0].size();

// DP array initialized with -1
vector<vector<int>> dp(2, vector<int>(n, -1));

// Start from Assembly Line 0
int line0 = solve(a, T, 0, 0, x, n, dp) + e[0] + a[0][0];

// Reset DP array
dp = vector<vector<int>>(2, vector<int>(n, -1));

// Start from Assembly Line 1
int line1 = solve(a, T, 1, 0, x, n, dp) + e[1] + a[1][0];

// Return minimum time
return min(line0, line1);

}

int main() { vector<vector> a = {{4, 5, 3, 2}, {2, 10, 1, 4}};

vector<vector<int>> T = {{0, 7, 4, 5}, {0, 9, 2, 8}};

vector<int> e = {10, 12};
vector<int> x = {18, 7};

int ans = carAssembly(a, T, e, x);

cout << ans << endl;

return 0;

}

Java

import java.util.*;

// Main Class public class GFG {

// Recursive + Memoization function
static int solve(int[][] a, int[][] T, int currentLine,
                 int currentStation, int[] x, int n,
                 int[][] dp)
{
    // Base Case:
    // If we are at the last station
    if (currentStation == n - 1) {
        return x[currentLine];
    }

    // If already computed
    if (dp[currentLine][currentStation] != -1) {
        return dp[currentLine][currentStation];
    }

    // Option 1:
    // Continue on same line
    int sameLine = solve(a, T, currentLine, currentStation + 1, x, n, dp)
                   + a[currentLine][currentStation + 1];

    // Option 2:
    // Switch to another line
    int changeLine
        = solve(a, T, 1 - currentLine, currentStation + 1, x, n, dp)
          + a[1 - currentLine][currentStation + 1]
          + T[currentLine][currentStation + 1];

    // Store and return minimum answer
    return dp[currentLine][currentStation]
        = Math.min(sameLine, changeLine);
}

// Function to find minimum assembly time
public static int carAssembly(int n, int[][] a, int[][] T, int[] e, int[] x)
{
    // DP array initialized with -1
    int[][] dp = new int[2][n];

    for (int i = 0; i < 2; i++) {
        Arrays.fill(dp[i], -1);
    }

    // Start from line 0
    int line0 = solve(a, T, 0, 0, x, n, dp) + e[0] + a[0][0];

    // Reset DP for second starting line
    for (int i = 0; i < 2; i++) {
        Arrays.fill(dp[i], -1);
    }

    // Start from line 1
    int line1 = solve(a, T, 1, 0, x, n, dp) + e[1] + a[1][0];

    // Return minimum time
    return Math.min(line0, line1);
}

public static void main(String[] args)
{
    int n = 4;

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

    int ans = carAssembly(n, a, T, e, x);

    System.out.println(ans);
}

}

Python

Recursive + Memoization function

def solve(a, T, currentLine, currentStation, x, n, dp):

# Base Case:
# If we are at the last station
if currentStation == n - 1:
    return x[currentLine]

# If already computed
if dp[currentLine][currentStation] != -1:
    return dp[currentLine][currentStation]

# Option 1:
# Continue on same line
sameLine = solve(a, T, currentLine, currentStation + 1, x,
                 n, dp) + a[currentLine][currentStation + 1]

# Option 2:
# Switch to another line
changeLine = solve(a, T, 1 - currentLine, currentStation + 1, x, n, dp) + \
    a[1 - currentLine][currentStation + 1] + \
    T[currentLine][currentStation + 1]

# Store and return minimum answer
dp[currentLine][currentStation] = min(sameLine, changeLine)

return dp[currentLine][currentStation]

Function to find minimum assembly time

def carAssembly(n, a, T, e, x):

# DP array initialized with -1
dp = [[-1 for _ in range(n)] for _ in range(2)]

# Start from line 0
line0 = solve(a, T, 0, 0, x, n, dp) + e[0] + a[0][0]

# Reset DP for second starting line
dp = [[-1 for _ in range(n)] for _ in range(2)]

# Start from line 1
line1 = solve(a, T, 1, 0, x, n, dp) + e[1] + a[1][0]

# Return minimum time
return min(line0, line1)

Driver Code

if name == "main": n = 4

a = [[4, 5, 3, 2], [2, 10, 1, 4]]

T = [[0, 7, 4, 5], [0, 9, 2, 8]]

e = [10, 12]
x = [18, 7]

ans = carAssembly(n, a, T, e, x)

print(ans)

C#

using System;

class GFG {

// Recursive + Memoization function
static int Solve(int[][] a, int[][] T, int currentLine,
                 int currentStation, int[] x, int n,
                 int[][] dp)
{
    // Base Case:
    // If we are at the last station
    if (currentStation == n - 1) {
        return x[currentLine];
    }

    // If already computed
    if (dp[currentLine][currentStation] != -1) {
        return dp[currentLine][currentStation];
    }

    // Option 1:
    // Continue on same line
    int sameLine = Solve(a, T, currentLine, currentStation + 1, x, n, dp)
                   + a[currentLine][currentStation + 1];

    // Option 2:
    // Switch to another line
    int changeLine
        = Solve(a, T, 1 - currentLine, currentStation + 1, x, n, dp)
          + a[1 - currentLine][currentStation + 1]
          + T[currentLine][currentStation + 1];

    // Store and return minimum answer
    dp[currentLine][currentStation]
        = Math.Min(sameLine, changeLine);

    return dp[currentLine][currentStation];
}

// Function to find minimum assembly time
static int carAssembly(int[][] a, int[][] T, int[] e, int[] x)
{
    int n = a[0].Length;

    // DP array initialized with -1
    int[][] dp = new int[2][];

    for (int i = 0; i < 2; i++) {
        dp[i] = new int[n];

        for (int j = 0; j < n; j++) {
            dp[i][j] = -1;
        }
    }

    // Start from line 0
    int line0 = Solve(a, T, 0, 0, x, n, dp) + e[0] + a[0][0];

    // Reset DP for second starting line
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < n; j++) {
            dp[i][j] = -1;
        }
    }

    // Start from line 1
    int line1 = Solve(a, T, 1, 0, x, n, dp) + e[1] + a[1][0];

    // Return minimum time
    return Math.Min(line0, line1);
}
static void Main()
{
    int[][] a
        = new int[][] { new int[] { 4, 5, 3, 2 },
                        new int[] { 2, 10, 1, 4 } };

    int[][] T
        = new int[][] { new int[] { 0, 7, 4, 5 },
                        new int[] { 0, 9, 2, 8 } };

    int[] e = { 10, 12 };
    int[] x = { 18, 7 };

    int ans = carAssembly(a, T, e, x);

    Console.WriteLine(ans);
}

}

JavaScript

// Recursive + Memoization function function solve(a, T, currentLine, currentStation, x, n, dp) { // Base Case: // If we are at the last station if (currentStation === n - 1) { return x[currentLine]; }

// If already computed
if (dp[currentLine][currentStation] !== -1) {
    return dp[currentLine][currentStation];
}

// Option 1:
// Continue on same line
let sameLine = solve(a, T, currentLine,
                     currentStation + 1, x, n, dp)
               + a[currentLine][currentStation + 1];

// Option 2:
// Switch to another line
let changeLine
    = solve(a, T, 1 - currentLine, currentStation + 1,
            x, n, dp)
      + a[1 - currentLine][currentStation + 1]
      + T[currentLine][currentStation + 1];

// Store and return minimum answer
dp[currentLine][currentStation]
    = Math.min(sameLine, changeLine);

return dp[currentLine][currentStation];

}

// Function to find minimum assembly time function carAssembly(a, T, e, x) { let n = a[0].length;

// DP array initialized with -1
let dp
    = Array.from({length : 2}, () => Array(n).fill(-1));

// Start from line 0
let line0
    = solve(a, T, 0, 0, x, n, dp) + e[0] + a[0][0];

// Reset DP for second starting line
dp = Array.from({length : 2}, () => Array(n).fill(-1));

// Start from line 1
let line1
    = solve(a, T, 1, 0, x, n, dp) + e[1] + a[1][0];

// Return minimum time
return Math.min(line0, line1);

}

// Driver Code

let a = [ [ 4, 5, 3, 2 ], [ 2, 10, 1, 4 ] ];

let T = [ [ 0, 7, 4, 5 ], [ 0, 9, 2, 8 ] ];

let e = [ 10, 12 ]; let x = [ 18, 7 ];

let ans = carAssembly(a, T, e, x);

console.log(ans);

`

[Expected Approach - 2] Using Bottom Up(DP) - O(n) Time and O(n) Space

In the **Bottom-Up DP approach, we build the solution iteratively instead of using recursion.
dp[line][i] stores the minimum time required to reach station i on a particular assembly line. For every station, we either continue on the same line or switch from the other line by paying the transfer cost, and store the minimum of both choices. Finally, we add the exit times and return the minimum overall assembly time.

#include #include #include using namespace std;

// Function to find minimum assembly time int carAssembly(vector<vector> &a, vector<vector> &T, vector &e, vector &x) { int n = a[0].size();

// dp[0][i] -> Minimum time to reach station i on line 0
// dp[1][i] -> Minimum time to reach station i on line 1
vector<vector<int>> dp(2, vector<int>(n));

// Base Case:
// Add entry time and first station time
dp[0][0] = e[0] + a[0][0];
dp[1][0] = e[1] + a[1][0];

// Fill DP table
for (int i = 1; i < n; i++)
{
    // Stay on same line OR switch from other line
    dp[0][i] = min(dp[0][i - 1] + a[0][i], dp[1][i - 1] + T[1][i] + a[0][i]);

    dp[1][i] = min(dp[1][i - 1] + a[1][i], dp[0][i - 1] + T[0][i] + a[1][i]);
}

// Add exit times
return min(dp[0][n - 1] + x[0], dp[1][n - 1] + x[1]);

}

int main() { vector<vector> a = {{4, 5, 3, 2}, {2, 10, 1, 4}};

vector<vector<int>> T = {{0, 7, 4, 5}, {0, 9, 2, 8}};

vector<int> e = {10, 12};
vector<int> x = {18, 7};

int ans = carAssembly(a, T, e, x);

cout << ans << endl;

return 0;

}

Java

import java.util.*;

// Main Class public class GFG {

// Function to find minimum assembly time
public static int carAssembly(int n, int[][] a,
                              int[][] T, int[] e,
                              int[] x)
{
    // dp[0][i] -> Minimum time to reach station i on
    // line 0 dp[1][i] -> Minimum time to reach station
    // i on line 1
    int[][] dp = new int[2][n];

    // Base Case:
    // Add entry time and first station time
    dp[0][0] = e[0] + a[0][0];
    dp[1][0] = e[1] + a[1][0];

    // Fill DP table
    for (int i = 1; i < n; i++) {
        // Stay on same line OR switch from other line
        dp[0][i] = Math.min(dp[0][i - 1] + a[0][i], dp[1][i - 1] + T[1][i] + a[0][i]);

        dp[1][i] = Math.min(dp[1][i - 1] + a[1][i], dp[0][i - 1] + T[0][i] + a[1][i]);
    }

    // Add exit times
    return Math.min(dp[0][n - 1] + x[0], dp[1][n - 1] + x[1]);
}

public static void main(String[] args)
{
    int n = 4;

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

    int ans = carAssembly(n, a, T, e, x);

    System.out.println(ans);
}

}

Python

Function to find minimum assembly time

def carAssembly(n, a, T, e, x):

# dp[0][i] -> Minimum time to reach station i on line 0
# dp[1][i] -> Minimum time to reach station i on line 1
dp = [[0 for _ in range(n)] for _ in range(2)]

# Base Case:
# Add entry time and first station time
dp[0][0] = e[0] + a[0][0]
dp[1][0] = e[1] + a[1][0]

# Fill DP table
for i in range(1, n):

    # Stay on same line OR switch from other line
    dp[0][i] = min( dp[0][i - 1] + a[0][i], dp[1][i - 1] + T[1][i] + a[0][i])

    dp[1][i] = min(dp[1][i - 1] + a[1][i], dp[0][i - 1] + T[0][i] + a[1][i])

# Add exit times
return min(dp[0][n - 1] + x[0], dp[1][n - 1] + x[1])

Driver Code

if name == "main": n = 4

a = [[4, 5, 3, 2], [2, 10, 1, 4]]

T = [[0, 7, 4, 5], [0, 9, 2, 8]]

e = [10, 12]
x = [18, 7]

ans = carAssembly(n, a, T, e, x)

print(ans)

C#

using System;

class GFG {

// Function to find minimum assembly time
static int carAssembly(int[][] a, int[][] T, int[] e, int[] x)
{
    int n = a[0].Length;

    // dp[0][i] -> Minimum time to reach station i on
    // line 0 dp[1][i] -> Minimum time to reach station
    // i on line 1
    int[][] dp = new int[2][];

    dp[0] = new int[n];
    dp[1] = new int[n];

    // Base Case:
    // Add entry time and first station time
    dp[0][0] = e[0] + a[0][0];
    dp[1][0] = e[1] + a[1][0];

    // Fill DP table
    for (int i = 1; i < n; i++) {
        // Stay on same line OR switch from other line
        dp[0][i] = Math.Min(dp[0][i - 1] + a[0][i], dp[1][i - 1] + T[1][i] + a[0][i]);

        dp[1][i] = Math.Min(dp[1][i - 1] + a[1][i], dp[0][i - 1] + T[0][i] + a[1][i]);
    }

    // Add exit times
    return Math.Min(dp[0][n - 1] + x[0], dp[1][n - 1] + x[1]);
}
static void Main()
{
    int[][] a
        = new int[][] { new int[] { 4, 5, 3, 2 },
                        new int[] { 2, 10, 1, 4 } };

    int[][] T
        = new int[][] { new int[] { 0, 7, 4, 5 },
                        new int[] { 0, 9, 2, 8 } };

    int[] e = { 10, 12 };
    int[] x = { 18, 7 };

    int ans = carAssembly(a, T, e, x);

    Console.WriteLine(ans);
}

}

JavaScript

// Function to find minimum assembly time function carAssembly(a, T, e, x) { let n = a[0].length;

// dp[0][i] -> Minimum time to reach station i on
// line 0 dp[1][i] -> Minimum time to reach station
// i on line 1
let dp
    = Array.from({length : 2}, () => Array(n).fill(0));

// Base Case:
// Add entry time and first station time
dp[0][0] = e[0] + a[0][0];
dp[1][0] = e[1] + a[1][0];

// Fill DP table
for (let i = 1; i < n; i++) {
    // Stay on same line OR switch from other line
    dp[0][i]
        = Math.min(dp[0][i - 1] + a[0][i], dp[1][i - 1] + T[1][i] + a[0][i]);

    dp[1][i]
        = Math.min(dp[1][i - 1] + a[1][i], dp[0][i - 1] + T[0][i] + a[1][i]);
}

// Add exit times
return Math.min(dp[0][n - 1] + x[0], dp[1][n - 1] + x[1]);

}

// Driver Code

let a = [ [ 4, 5, 3, 2 ], [ 2, 10, 1, 4 ] ];

let T = [ [ 0, 7, 4, 5 ], [ 0, 9, 2, 8 ] ];

let e = [ 10, 12 ]; let x = [ 18, 7 ];

let ans = carAssembly(a, T, e, x);

console.log(ans);

`