logo

Gewichtete Jobplanung | Set 2 (mit LIS)

Gegeben sind N Jobs, bei denen jeder Job durch die folgenden drei Elemente repräsentiert wird.
1. Startzeit 
2. Endzeit 
3. Mit Gewinn oder Wert verbunden
Finden Sie die Teilmenge der Jobs mit dem maximalen Gewinn, sodass sich keine zwei Jobs in der Teilmenge überschneiden.

Beispiele:  



Array in Java sortiert
    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 vorherige Beitrag, den wir über das Problem der gewichteten Jobplanung besprochen haben. Wir haben eine DP-Lösung besprochen, bei der wir den aktuellen Job grundsätzlich einbeziehen oder ausschließen. In diesem Beitrag wird eine weitere interessante DP-Lösung besprochen, bei der wir auch die Jobs drucken. Dieses Problem ist eine Variation des Standards Längste ansteigende Teilsequenz (LIS) Problem. Wir benötigen eine geringfügige Änderung in der dynamischen Programmierlösung des LIS-Problems.

Zuerst müssen wir die Jobs nach der Startzeit sortieren. Job[0..n-1] sei das Array der Jobs nach der Sortierung. Wir definieren den Vektor L so, dass L[i] selbst ein Vektor ist, der die gewichtete Jobplanung von Job[0..i] speichert, die mit Job[i] endet. Daher kann für einen Index i L[i] rekursiv geschrieben werden als - 

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


Betrachten Sie zum Beispiel Paare {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}

Wir wählen den Vektor mit dem höchsten Gewinn. In diesem Fall L[1].

Unten ist die Umsetzung der oben genannten Idee – 

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<Job> 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<Job> &arr) {  // Sort arr[] by start time.  sort(arr.begin() arr.end() compare);  // L[i] 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 << ') '; } // 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; } 
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<Job> 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<Job> arr) {    // Sort arr[] by start time.  Collections.sort(arr new Comparator<Job>()   {  @Override  public int compare(Job x Job y)   {  return x.start - y.start;  }  });    // sort(arr.begin() arr.end() compare);  // L[i] stores Weighted Job Scheduling of  // job[0..i] that ends with job[i]  ArrayList<ArrayList<Job>> L = new ArrayList<>();  for(int i = 0; i < arr.size(); i++)  {  L.add(new ArrayList<>());  }  // L[0] is equal to arr[0]  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<Job> copied = new ArrayList<>(  L.get(j));  L.set(i copied);  }  }  L.get(i).add(arr.get(i));  }  ArrayList<Job> 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<Job> arr = new ArrayList<>(  Arrays.asList(a));  findMaxProfit(arr); } } // This code is contributed by sanjeev2552 
Python
# Python program for weighted job scheduling using LIS import sys # A job has start time finish time and profit. class Job: def __init__(self start finish profit): self.start = start self.finish = finish self.profit = profit # Utility function to calculate sum of all vector elements def findSum(arr): sum = 0 for i in range(len(arr)): sum += arr[i].profit return sum # comparator function for sort function def compare(x y): if x.start < y.start: return -1 elif x.start == y.start: return 0 else: return 1 # The main function that finds the maximum possible profit from given array of jobs def findMaxProfit(arr): # Sort arr[] by start time. arr.sort(key=lambda x: x.start) # L[i] stores Weighted Job Scheduling of job[0..i] that ends with job[i] L = [[] for _ in range(len(arr))] # L[0] is equal to arr[0] L[0].append(arr[0]) # start from index 1 for i in range(1 len(arr)): # for every j less than i for j in range(i): # L[i] = {MaxSum(L[j])} + arr[i] where j < i # and arr[j].finish <= arr[i].start if arr[j].finish <= arr[i].start and findSum(L[j]) > findSum(L[i]): L[i] = L[j][:] L[i].append(arr[i]) maxChain = [] # find one with max profit for i in range(len(L)): if findSum(L[i]) > findSum(maxChain): maxChain = L[i] for i in range(len(maxChain)): print('({} {} {})'.format( maxChain[i].start maxChain[i].finish maxChain[i].profit) end=' ') # Driver Function if __name__ == '__main__': a = [Job(3 10 20) Job(1 2 50) Job(6 19 100) Job(2 100 200)] findMaxProfit(a) 
C#
using System; using System.Collections.Generic; using System.Linq; public class Graph {  // A job has start time finish time  // and profit.  public class Job  {  public 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  public static int FindSum(List<Job> arr)   {  int sum = 0;    for(int i = 0; i < arr.Count; i++)  sum += arr.ElementAt(i).profit;    return sum;  }  // The main function that finds the maximum  // possible profit from given array of jobs  public static void FindMaxProfit(List<Job> arr)  {    // Sort arr[] by start time.  arr.Sort((x y) => x.start.CompareTo(y.start));  // L[i] stores Weighted Job Scheduling of  // job[0..i] that ends with job[i]  List<List<Job>> L = new List<List<Job>>();  for(int i = 0; i < arr.Count; i++)  {  L.Add(new List<Job>());  }  // L[0] is equal to arr[0]  L[0].Add(arr[0]);  // Start from index 1  for(int i = 1; i < arr.Count; 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])))  {  List<Job> copied = new List<Job>(  L[j]);  L[i] = copied;  }  }  L[i].Add(arr[i]);  }  List<Job> maxChain = new List<Job>();  // Find one with max profit  for(int i = 0; i < L.Count; i++)  if (FindSum(L[i]) > FindSum(maxChain))  maxChain = L[i];  for(int i = 0; i < maxChain.Count; i++)   {  Console.WriteLine('({0} {1} {2})'   maxChain[i].start   maxChain[i].finish  maxChain[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) };  List<Job> arr = new List<Job>(a);  FindMaxProfit(arr);  } } 
JavaScript
// JavaScript program for weighted job scheduling using LIS // A job has start time finish time and profit. function Job(start finish profit) {  this.start = start;  this.finish = finish;  this.profit = profit; } // Utility function to calculate sum of all vector // elements function findSum(arr) {  let sum = 0;  for (let i = 0; i < arr.length; i++) {  sum += arr[i].profit;  }  return sum; } // comparator function for sort function function compare(x y) {  return x.start < y.start; } // The main function that finds the maximum possible // profit from given array of jobs function findMaxProfit(arr) {  // Sort arr[] by start time.  arr.sort(compare);  // L[i] stores Weighted Job Scheduling of  // job[0..i] that ends with job[i]  let L = new Array(arr.length).fill([]);  // L[0] is equal to arr[0]  L[0] = [arr[0]];  // start from index 1  for (let i = 1; i < arr.length; i++) {  // for every j less than i  for (let 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(arr[i]);  }  let maxChain = [];  // find one with max profit  for (let i = 0; i < L.length; i++) {  if (findSum(L[i]) > findSum(maxChain)) {  maxChain = L[i];  }  }  for (let i = 0; i < maxChain.length; i++) {  console.log(  '(' +  maxChain[i].start +  ' ' +  maxChain[i].finish +  ' ' +  maxChain[i].profit +  ') '  );  } } // Driver Function let a = [  new Job(3 10 20)  new Job(1 2 50)  new Job(2 100 200) ]; findMaxProfit(a); 

Ausgabe
(1 2 50) (2 100 200) 


Wir können die obige DP-Lösung weiter optimieren, indem wir die Funktion findSum() entfernen. Stattdessen können wir einen anderen Vektor/ein anderes Array verwalten, um die Summe des maximal möglichen Gewinns bis zum Job i zu speichern.



Zeitkomplexität Die obige dynamische Programmierlösung ist O(n2), wobei n die Anzahl der Jobs ist. 
Hilfsraum vom Programm verwendet wird, ist O(n2).

0,0625 als Bruch