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[0] = {job[0]}
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[0]: {1, 2, 50}
L[1]: {1, 2, 50} {2, 100, 200}
L[2]: {1, 2, 50} {3, 10, 20}
L[3]: {1, 2, 50} {6, 19, 100}
We choose the vector with highest profit. In this case, L[1].
Below is C++ implementation of above idea –
// C++ program for weighted job scheduling using LIS #include <iostream> #include <vector> #include <algorithm> 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<Job> arr) { int sum = 0; for (int i = 0; i < arr.size(); i++) sum += arr[i].profit; return sum; } // The main function that finds the maximum possible // profit from given array of jobs void findMaxProfit(vector<Job> &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<vector<Job>> L(arr.size()); // L[0] is equal to arr[0] L[0].push_back(arr[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[j].finish <= arr[i].start) && (findSum(L[j]) > findSum(L[i]))) L[i] = L[j]; } L[i].push_back(arr[i]); } vector<Job> 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 << ") "; } // comparator function for sort function int compare(Job x, Job y) { return x.start < y.start; } // Driver Function int main() { Job a[] = { {3, 10, 20}, {1, 2, 50}, {6, 19, 100}, {2, 100, 200} }; int n = sizeof(a) / sizeof(a[0]); vector<Job> arr(a, a + n); findMaxProfit(arr); return 0; } |
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).
This article is contributed by Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.
Recommended Posts:
- Construction of Longest Increasing Subsequence(LIS) and printing LIS sequence
- Weighted Job Scheduling
- Weighted Job Scheduling in O(n Log n) time
- Find Jobs involved in Weighted Job Scheduling
- LIS using Segment Tree
- Minimum concatenation required to get strictly LIS for array with repetitive elements | Set-2
- Variations of LIS | DP-21
- Longest Common Increasing Subsequence (LCS + LIS)
- Size of array after repeated deletion of LIS
- Maximum weighted edge in path between two nodes in an N-ary tree using binary lifting
- Shortest path with exactly k edges in a directed and weighted graph | Set 2
- Shortest path with exactly k edges in a directed and weighted graph
- Queries to find sum of distance of a given node to every leaf node in a Weighted Tree
- Assembly Line Scheduling | DP-34
- Minimum halls required for class scheduling
- Maximum sum subarray having sum less than or equal to given sum using Set
- Partition of a set into K subsets with equal sum using BitMask and DP
- Count total set bits in all numbers from 1 to N | Set 3
- Count the number of ways to tile the floor of size n x m using 1 x m size tiles
- Maximum Subarray Sum using Divide and Conquer algorithm
Improved By : Akanksha_Rai

