Open In App

Job Sequencing Problem – Loss Minimization

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

We are given N jobs numbered 1 to N. For each activity, let Ti denotes the number of days required to complete the job. For each day of delay before starting to work for job i, a loss of Li is incurred. We are required to find a sequence to complete the jobs so that overall loss is minimized. We can only work on one job at a time. If multiple such solutions are possible, then we are required to give the lexicographically least permutation (i.e earliest in dictionary order). Examples:

Input : L = {3, 1, 2, 4} and 
        T = {4, 1000, 2, 5}
Output : 3, 4, 1, 2
Explanation: We should first complete 
job 3, then jobs 4, 1, 2 respectively.

Input : L = {1, 2, 3, 5, 6} 
        T = {2, 4, 1, 3, 2}
Output : 3, 5, 4, 1, 2 
Explanation: We should complete jobs 
3, 5, 4, 1 and then 2 in this order.

Let us consider two extreme cases and we shall deduce the general case solution from them.

  1. All jobs take same time to finish, i.e Ti = k for all i. Since all jobs take same time to finish we should first select jobs which have large Loss (Li). We should select jobs which have the highest losses and finish them as early as possible. Thus this is a greedy algorithm. Sort the jobs in descending order based on Li only.
  2. All jobs have the same penalty. Since all jobs have the same penalty we will do those jobs first which will take less amount of time to finish. This will minimize the total delay, and hence also the total loss incurred. This is also a greedy algorithm. Sort the jobs in ascending order based on Ti. Or we can also sort in descending order of 1/Ti.

From the above cases, we can easily see that we should sort the jobs not on the basis of Li or Ti alone. Instead, we should sort the jobs according to the ratio Li/Ti, in descending order.

We can get the lexicographically smallest permutation of jobs if we perform a stable sort on the jobs. An example of a stable sort is merge sort.

To get most accurate result avoid dividing Li by Ti. Instead, compare the two ratios like fractions. To compare a/b and c/d, compare ad and bc.

C++




// CPP program to minimize loss using stable sort.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
 
#define all(c) c.begin(), c.end()
 
// Each job is represented as a pair of int and pair.
// This is done to provide implementation simplicity
// so that we can use functions provided by algorithm
// header
typedef pair<int, pair<int, int> > job;
 
// compare function is given so that we can specify
// how to compare a pair of jobs
bool cmp_pair(job a, job b)
{
    int a_Li, a_Ti, b_Li, b_Ti;
    a_Li = a.second.first;
    a_Ti = a.second.second;
    b_Li = b.second.first;
    b_Ti = b.second.second;
 
    // To compare a/b and c/d, compare ad and bc
    return (a_Li * b_Ti) > (b_Li * a_Ti);
}
 
void printOptimal(int L[], int T[], int N)
{
    vector<job> list; // (Job Index, Si, Ti)
 
    for (int i = 0; i < N; i++) {
        int t = T[i];
        int l = L[i];
 
        // Each element is: (Job Index, (Li, Ti) )
        list.push_back(make_pair(i + 1, make_pair(l, t)));
    }
 
    stable_sort(all(list), cmp_pair);
 
    // traverse the list and print job numbers
    cout << "Job numbers in optimal sequence are\n";
    for (int i = 0; i < N; i++)
        cout << list[i].first << " ";
 
}
 
// Driver code
int main()
{
    int L[] = { 1, 2, 3, 5, 6 };
    int T[] = { 2, 4, 1, 3, 2 };
    int N = sizeof(L) / sizeof(L[0]);
    printOptimal(L, T, N);
    return 0;
}


Java




//Java program to minimize loss using stable sort.
 
import java.io.*;
import java.util.*;
 
class GFG {
     
    // compare function is given so that we can specify
    // how to compare a pair of jobs
    public static class cmp_pair implements Comparator<job>
    {
        @Override
        public int compare(job a, job b){
            int a_Li, a_Ti, b_Li, b_Ti;
            a_Li = a.li;
            a_Ti = a.ti;
            b_Li = b.li;
            b_Ti = b.ti;
           
            // To compare a/b and c/d, compare ad and bc
            return (a_Li * b_Ti) > (b_Li * a_Ti)?-1:1;
        }
    }
     
    public static void printOptimal(int L[], int T[], int N)
    {
        List<job> list = new ArrayList<>(); // (Job Index, Si, Ti)
       
        for (int i = 0; i < N; i++) {
            int t = T[i];
            int l = L[i];
       
            // Each element is: (Job Index, (Li, Ti) )
            list.add(new job(i + 1, l, t));
        }
       
        Collections.sort(list,new cmp_pair());
       
        // traverse the list and print job numbers
        System.out.println("Job numbers in optimal sequence are");
        for (int i = 0; i < N; i++)
            System.out.print(list.get(i).index+" ");  
       
    }
     
    public static void main (String[] args) {
        int L[] = { 1, 2, 3, 5, 6 };
        int T[] = { 2, 4, 1, 3, 2 };
        int N = L.length;
        printOptimal(L, T, N);
    }
}
 
// Each job is represented as a pair of int and pair.
// This is done to provide implementation simplicity
// so that we can use functions provided by algorithm
// header
class job{
    int index,ti,li;
    job(int i,int l, int t){
        this.index=i;
        this.ti=t;
        this.li=l;
    }
}
 
//This code is contributed by shruti456rawal


Python3




# Python program to minimize loss using stable sort.
import functools
import operator
from typing import List
 
# compare function is given so that we can specify
# how to compare a pair of jobs
class cmp_pair:
    def __call__(self, a, b):
        a_Li, a_Ti, b_Li, b_Ti = a.li, a.ti, b.li, b.ti
         
        # To compare a/b and c/d, compare ad and bc
        return -1 if (a_Li * b_Ti) > (b_Li * a_Ti) else 1
 
class job:
    def __init__(self, i, l, t):
        self.index, self.ti, self.li = i, t, l
 
def printOptimal(L: List[int], T: List[int], N: int) -> None:
    job_list = []
    for i in range(N):
        t, l = T[i], L[i]
         
        # Each element is: (Job Index, (Li, Ti) )
        job_list.append(job(i + 1, l, t))
    job_list.sort(key=functools.cmp_to_key(cmp_pair()))
     
    # traverse the list and print job numbers
    print("Job numbers in optimal sequence are")
    for i in range(N):
        print(job_list[i].index, end=" ")
 
L = [1, 2, 3, 5, 6]
T = [2, 4, 1, 3, 2]
N = len(L)
printOptimal(L, T, N)
 
# This code is contributed by Prince


Javascript




// JavaScript program for the above approach
 
function cmp_pair(a, b) {
  const a_Li = a.li, a_Ti = a.ti, b_Li = b.li, b_Ti = b.ti;
   
  // To compare a/b and c/d, compare ad and bc
  return (a_Li * b_Ti) > (b_Li * a_Ti) ? -1 : 1;
}
 
class job {
  constructor(i, l, t) {
    this.index = i;
    this.ti = t;
    this.li = l;
  }
}
 
function printOptimal(L, T, N) {
  const job_list = [];
  for (let i = 0; i < N; i++) {
    const t = T[i], l = L[i];
     
    // Each element is: (Job Index, (Li, Ti) )
    job_list.push(new job(i + 1, l, t));
  }
  job_list.sort(cmp_pair);
   
  // traverse the list and print job numbers
  console.log("Job numbers in optimal sequence are");
  for (let i = 0; i < N; i++) {
    process.stdout.write(job_list[i].index + " ");
  }
}
 
const L = [1, 2, 3, 5, 6];
const T = [2, 4, 1, 3, 2];
const N = L.length;
printOptimal(L, T, N);
 
// This code is contributed by adityashatmfh


C#




<div id="highlighter_942247" class="syntaxhighlighter nogutter  "><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="comments">//C# program to minimize loss using stable sort.</code></div><div class="line number2 index1 alt1"> </div><div class="line number3 index2 alt2"><code class="keyword">using</code> <code class="plain">System;</code></div><div class="line number4 index3 alt1"><code class="keyword">using</code> <code class="plain">System.Collections.Generic;</code></div><div class="line number5 index4 alt2"> </div><div class="line number6 index5 alt1"><code class="keyword">public</code> <code class="keyword">class</code> <code class="plain">GFG {</code></div><div class="line number7 index6 alt2"><code class="undefined spaces">    </code> </div><div class="line number8 index7 alt1"><code class="undefined spaces">    </code><code class="comments">// compare function is given so that we can specify</code></div><div class="line number9 index8 alt2"><code class="undefined spaces">    </code><code class="comments">// how to compare a pair of jobs</code></div><div class="line number10 index9 alt1"><code class="undefined spaces">    </code><code class="keyword">public</code> <code class="keyword">class</code> <code class="plain">Cmp_pair : IComparer<job>{</code></div><div class="line number11 index10 alt2"><code class="undefined spaces">        </code><code class="keyword">public</code> <code class="keyword">int</code> <code class="plain">Compare(job a, job b){</code></div><div class="line number12 index11 alt1"><code class="undefined spaces">            </code><code class="keyword">int</code> <code class="plain">a_Li, a_Ti, b_Li, b_Ti;</code></div><div class="line number13 index12 alt2"><code class="undefined spaces">            </code><code class="plain">a_Li = a.li;</code></div><div class="line number14 index13 alt1"><code class="undefined spaces">            </code><code class="plain">a_Ti = a.ti;</code></div><div class="line number15 index14 alt2"><code class="undefined spaces">            </code><code class="plain">b_Li = b.li;</code></div><div class="line number16 index15 alt1"><code class="undefined spaces">            </code><code class="plain">b_Ti = b.ti;</code></div><div class="line number17 index16 alt2"><code class="undefined spaces">          </code> </div><div class="line number18 index17 alt1"><code class="undefined spaces">            </code><code class="comments">// To compare a/b and c/d, compare ad and bc</code></div><div class="line number19 index18 alt2"><code class="undefined spaces">            </code><code class="keyword">return</code> <code class="plain">(a_Li * b_Ti) > (b_Li * a_Ti)?-1:1;</code></div><div class="line number20 index19 alt1"><code class="undefined spaces">        </code><code class="plain">}</code></div><div class="line number21 index20 alt2"><code class="undefined spaces">    </code><code class="plain">}</code></div><div class="line number22 index21 alt1"><code class="undefined spaces">    </code> </div><div class="line number23 index22 alt2"><code class="undefined spaces">    </code><code class="keyword">public</code> <code class="keyword">static</code> <code class="keyword">void</code> <code class="plain">printOptimal(</code><code class="keyword">int</code><code class="plain">[] L, </code><code class="keyword">int</code><code class="plain">[] T, </code><code class="keyword">int</code> <code class="plain">N)</code></div><div class="line number24 index23 alt1"><code class="undefined spaces">    </code><code class="plain">{</code></div><div class="line number25 index24 alt2"><code class="undefined spaces">        </code><code class="plain">List<job> list = </code><code class="keyword">new</code> <code class="plain">List<job>(); </code><code class="comments">// (Job Index, Si, Ti)</code></div><div class="line number26 index25 alt1"><code class="undefined spaces">      </code> </div><div class="line number27 index26 alt2"><code class="undefined spaces">        </code><code class="keyword">for</code> <code class="plain">(</code><code class="keyword">int</code> <code class="plain">i = 0; i < N; i++) {</code></div><div class="line number28 index27 alt1"><code class="undefined spaces">            </code><code class="keyword">int</code> <code class="plain">t = T[i];</code></div><div class="line number29 index28 alt2"><code class="undefined spaces">            </code><code class="keyword">int</code> <code class="plain">l = L[i];</code></div><div class="line number30 index29 alt1"><code class="undefined spaces">      </code> </div><div class="line number31 index30 alt2"><code class="undefined spaces">            </code><code class="comments">// Each element is: (Job Index, (Li, Ti) )</code></div><div class="line number32 index31 alt1"><code class="undefined spaces">            </code><code class="plain">list.Add(</code><code class="keyword">new</code> <code class="plain">job(i + 1, l, t));</code></div><div class="line number33 index32 alt2"><code class="undefined spaces">        </code><code class="plain">}</code></div><div class="line number34 index33 alt1"><code class="undefined spaces">      </code> </div><div class="line number35 index34 alt2"><code class="undefined spaces">        </code><code class="plain">list.Sort(</code><code class="keyword">new</code> <code class="plain">Cmp_pair());</code></div><div class="line number36 index35 alt1"><code class="undefined spaces">      </code> </div><div class="line number37 index36 alt2"><code class="undefined spaces">        </code><code class="comments">// traverse the list and print job numbers</code></div><div class="line number38 index37 alt1"><code class="undefined spaces">        </code><code class="plain">Console.WriteLine(</code><code class="string">"Job numbers in optimal sequence are"</code><code class="plain">);</code></div><div class="line number39 index38 alt2"><code class="undefined spaces">        </code><code class="keyword">foreach</code><code class="plain">(job j </code><code class="keyword">in</code> <code class="plain">list)</code></div><div class="line number40 index39 alt1"><code class="undefined spaces">            </code><code class="plain">Console.Write(j.index+</code><code class="string">" "</code><code class="plain">);   </code></div><div class="line number41 index40 alt2"><code class="undefined spaces">      </code> </div><div class="line number42 index41 alt1"><code class="undefined spaces">    </code><code class="plain">}</code></div><div class="line number43 index42 alt2"><code class="undefined spaces">    </code> </div><div class="line number44 index43 alt1"><code class="undefined spaces">    </code><code class="keyword">public</code> <code class="keyword">static</code> <code class="keyword">void</code> <code class="plain">Main () {</code></div><div class="line number45 index44 alt2"><code class="undefined spaces">        </code><code class="keyword">int</code><code class="plain">[] L = { 1, 2, 3, 5, 6 };</code></div><div class="line number46 index45 alt1"><code class="undefined spaces">        </code><code class="keyword">int</code><code class="plain">[] T = { 2, 4, 1, 3, 2 };</code></div><div class="line number47 index46 alt2"><code class="undefined spaces">        </code><code class="keyword">int</code> <code class="plain">N = L.Length;</code></div><div class="line number48 index47 alt1"><code class="undefined spaces">        </code><code class="plain">printOptimal(L, T, N);</code></div><div class="line number49 index48 alt2"><code class="undefined spaces">    </code><code class="plain">}</code></div><div class="line number50 index49 alt1"><code class="plain">}</code></div><div class="line number51 index50 alt2"> </div><div class="line number52 index51 alt1"><code class="comments">// Each job is represented as a pair of int and pair.</code></div><div class="line number53 index52 alt2"><code class="comments">// This is done to provide implementation simplicity</code></div><div class="line number54 index53 alt1"><code class="comments">// so that we can use functions provided by algorithm</code></div><div class="line number55 index54 alt2"><code class="comments">// header</code></div><div class="line number56 index55 alt1"><code class="keyword">public</code> <code class="keyword">class</code> <code class="plain">job{</code></div><div class="line number57 index56 alt2"><code class="undefined spaces">    </code><code class="keyword">public</code> <code class="keyword">int</code> <code class="plain">index,ti,li;</code></div><div class="line number58 index57 alt1"><code class="undefined spaces">    </code><code class="keyword">public</code> <code class="plain">job(</code><code class="keyword">int</code> <code class="plain">i,</code><code class="keyword">int</code> <code class="plain">l, </code><code class="keyword">int</code> <code class="plain">t){</code></div><div class="line number59 index58 alt2"><code class="undefined spaces">        </code><code class="keyword">this</code><code class="plain">.index=i;</code></div><div class="line number60 index59 alt1"><code class="undefined spaces">        </code><code class="keyword">this</code><code class="plain">.ti=t;</code></div><div class="line number61 index60 alt2"><code class="undefined spaces">        </code><code class="keyword">this</code><code class="plain">.li=l;</code></div><div class="line number62 index61 alt1"><code class="undefined spaces">    </code><code class="plain">}</code></div><div class="line number63 index62 alt2"><code class="plain">}</code></div></div></td></tr></tbody></table></div>


Output

Job numbers in optimal sequence are
3 5 4 1 2 

Time Complexity: O(N log N)
Space Complexity: O(N)



Last Updated : 27 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads