Related Articles

# Weighted Job Scheduling | Set 2 (Using LIS)

• Difficulty Level : Medium
• Last Updated : 10 Dec, 2020

Given N jobs where every job is represented by following three elements of it.
1. Start Time
2. Finish Time
3. Profit or Value Associated
Find the maximum profit subset of jobs such that no two jobs in the subset overlap.

Examples:

```Input:
Number of Jobs n = 4
Job Details {Start Time, Finish Time, Profit}
Job 1: {1, 2, 50}
Job 2: {3, 5, 20}
Job 3: {6, 19, 100}
Job 4: {2, 100, 200}

Output:
Job 1: {1, 2, 50}
Job 4: {2, 100, 200}

Explanation: We can get the maximum profit by
scheduling jobs 1 and 4 and maximum profit is 250.```

In previous post, we have discussed about Weighted Job Scheduling problem. We discussed a DP solution where we basically includes or excludes current job. In this post, another interesting DP solution is discussed where we also print the Jobs. This problem is a variation of standard Longest Increasing Subsequence (LIS) problem. We need a slight change in the Dynamic Programming solution of LIS problem.

We first need to sort jobs according to start time. Let job[0..n-1] be the array of jobs after sorting. We define vector L such that L[i] is itself is a vector that stores Weighted Job Scheduling of job[0..i] that ends with job[i]. Therefore for an index i, L[i] can be recursively written as –

```L = {job}
L[i] = {MaxSum(L[j])} + job[i] where j < i and job[j].finish <= job[i].start
= job[i], if there is no such j```

For example, consider pairs {3, 10, 20}, {1, 2, 50}, {6, 19, 100}, {2, 100, 200}

```After sorting we get,
{1, 2, 50}, {2, 100, 200}, {3, 10, 20}, {6, 19, 100}

Therefore,
L: {1, 2, 50}
L: {1, 2, 50} {2, 100, 200}
L: {1, 2, 50} {3, 10, 20}
L: {1, 2, 50} {6, 19, 100}```

We choose the vector with highest profit. In this case, L.

Below is the implementation of the above idea –

## C++

 `// C++ program for weighted job scheduling using LIS``#include ``#include ``#include ``using` `namespace` `std;` `// A job has start time, finish time and profit.``struct` `Job``{``    ``int` `start, finish, profit;``};` `// Utility function to calculate sum of all vector``// elements``int` `findSum(vector arr)``{``    ``int` `sum = 0;``    ``for` `(``int` `i = 0; i < arr.size(); i++)``        ``sum +=  arr[i].profit;``    ``return` `sum;``}` `// comparator function for sort function``int` `compare(Job x, Job y)``{``    ``return` `x.start < y.start;``}` `// The main function that finds the maximum possible``// profit from given array of jobs``void` `findMaxProfit(vector &arr)``{``    ``// Sort arr[] by start time.``    ``sort(arr.begin(), arr.end(), compare);` `    ``// L[i] stores stores Weighted Job Scheduling of``    ``// job[0..i] that ends with job[i]``    ``vector> L(arr.size());` `    ``// L is equal to arr``    ``L.push_back(arr);` `    ``// start from index 1``    ``for` `(``int` `i = 1; i < arr.size(); i++)``    ``{``        ``// for every j less than i``        ``for` `(``int` `j = 0; j < i; j++)``        ``{``            ``// L[i] = {MaxSum(L[j])} + arr[i] where j < i``            ``// and arr[j].finish <= arr[i].start``            ``if` `((arr[j].finish <= arr[i].start) &&``                ``(findSum(L[j]) > findSum(L[i])))``                ``L[i] = L[j];``        ``}``        ``L[i].push_back(arr[i]);``    ``}` `    ``vector maxChain;` `    ``// find one with max profit``    ``for` `(``int` `i = 0; i < L.size(); i++)``        ``if` `(findSum(L[i]) > findSum(maxChain))``            ``maxChain = L[i];` `    ``for` `(``int` `i = 0; i < maxChain.size(); i++)``        ``cout << ``"("` `<<  maxChain[i].start << ``", "` `<<``             ``maxChain[i].finish << ``", "``             ``<<  maxChain[i].profit << ``") "``;``}` `// Driver Function``int` `main()``{``    ``Job a[] = { {3, 10, 20}, {1, 2, 50}, {6, 19, 100},``                ``{2, 100, 200} };``    ``int` `n = ``sizeof``(a) / ``sizeof``(a);` `    ``vector arr(a, a + n);` `    ``findMaxProfit(arr);` `    ``return` `0;``}`

## Java

 `// Java program for weighted job``// scheduling using LIS``import` `java.util.ArrayList;``import` `java.util.Arrays;``import` `java.util.Collections;``import` `java.util.Comparator;` `class` `Graph{` `// A job has start time, finish time``// and profit.``static` `class` `Job``{``    ``int` `start, finish, profit;` `    ``public` `Job(``int` `start, ``int` `finish,``               ``int` `profit)``    ``{``        ``this``.start = start;``        ``this``.finish = finish;``        ``this``.profit = profit;``    ``}``};` `// Utility function to calculate sum of all``// ArrayList elements``static` `int` `findSum(ArrayList arr)``{``    ``int` `sum = ``0``;``    ` `    ``for``(``int` `i = ``0``; i < arr.size(); i++)``        ``sum += arr.get(i).profit;``        ` `    ``return` `sum;``}` `// The main function that finds the maximum``// possible profit from given array of jobs``static` `void` `findMaxProfit(ArrayList arr)``{``    ` `    ``// Sort arr[] by start time.``    ``Collections.sort(arr, ``new` `Comparator()``    ``{``        ``@Override``        ``public` `int` `compare(Job x, Job y)``        ``{``            ``return` `x.start - y.start;``        ``}``    ``});``    ` `    ``// sort(arr.begin(), arr.end(), compare);` `    ``// L[i] stores stores Weighted Job Scheduling of``    ``// job[0..i] that ends with job[i]``    ``ArrayList> L = ``new` `ArrayList<>();``    ``for``(``int` `i = ``0``; i < arr.size(); i++)``    ``{``        ``L.add(``new` `ArrayList<>());``    ``}` `    ``// L is equal to arr``    ``L.get(``0``).add(arr.get(``0``));` `    ``// Start from index 1``    ``for``(``int` `i = ``1``; i < arr.size(); i++)``    ``{``        ` `        ``// For every j less than i``        ``for``(``int` `j = ``0``; j < i; j++)``        ``{``            ` `            ``// L[i] = {MaxSum(L[j])} + arr[i] where j < i``            ``// and arr[j].finish <= arr[i].start``            ``if` `((arr.get(j).finish <= arr.get(i).start) &&``                ``(findSum(L.get(j)) > findSum(L.get(i))))``            ``{``                ``ArrayList copied = ``new` `ArrayList<>(``                    ``L.get(j));``                ``L.set(i, copied);``            ``}``        ``}``        ``L.get(i).add(arr.get(i));``    ``}` `    ``ArrayList maxChain = ``new` `ArrayList<>();` `    ``// Find one with max profit``    ``for``(``int` `i = ``0``; i < L.size(); i++)``        ``if` `(findSum(L.get(i)) > findSum(maxChain))``            ``maxChain = L.get(i);` `    ``for``(``int` `i = ``0``; i < maxChain.size(); i++)``    ``{``        ``System.out.printf(``"(%d, %d, %d)\n"``,``              ``maxChain.get(i).start,``              ``maxChain.get(i).finish,``              ``maxChain.get(i).profit);``    ``}``}` `// Driver code``public` `static` `void` `main(String[] args)``{``    ``Job[] a = { ``new` `Job(``3``, ``10``, ``20``),``                ``new` `Job(``1``, ``2``, ``50``),``                ``new` `Job(``6``, ``19``, ``100``),``                ``new` `Job(``2``, ``100``, ``200``) };` `    ``ArrayList arr = ``new` `ArrayList<>(``        ``Arrays.asList(a));` `    ``findMaxProfit(arr);``}``}` `// This code is contributed by sanjeev2552`

Output:

`(1, 2, 50) (2, 100, 200)`

We can further optimize above DP solution by removing findSum() function. Instead, we can maintain another vector/array to store sum of maximum profit possible till job i. The implementation can be seen here.

Time complexity of above Dynamic Programming solution is O(n2) where n is the number of Jobs.
Auxiliary space used by the program is O(n2).