logo

Nájdite pracovné miesta zapojené do váženého plánovania úloh

Vzhľadom na N pracovných miest, kde každé pracovné miesto je reprezentované nasledujúcimi tromi prvkami.
1. Čas začiatku 
2. Čas ukončenia 
3. Zisk alebo hodnota spojená
Nájdite podskupina pracovných miest spojené s maximálnym ziskom tak, aby sa žiadne dve pracovné miesta v podmnožine neprekrývali.

Príklady: 



  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:    Jobs involved in maximum profit are Job 1: {1 2 50} Job 4: {2 100 200}

In predchádzajúce príspevok sme diskutovali o probléme váženého plánovania úloh. Príspevok však pokrýval iba kód súvisiaci s nájdením maximálneho zisku. V tomto príspevku tiež vytlačíme úlohy spojené s maximálnym ziskom.

Nech arr[0..n-1] je vstupné pole úloh. Pole DP[] definujeme tak, že DP[i] ukladá zapojené úlohy, aby sa dosiahol maximálny zisk z poľa arr[0..i]. tj DP[i] ukladá riešenie podproblému arr[0..i]. Zvyšok algoritmu zostáva rovnaký, ako je uvedené v predchádzajúce príspevok.

Nižšie je jeho implementácia v C++:



CPP
// C++ program for weighted job scheduling using Dynamic // Programming and Binary Search #include    using namespace std; // A job has start time finish time and profit. struct Job {  int start finish profit; }; // to store subset of jobs struct weightedJob {  // vector of Jobs  vector<Job> job;  // find profit associated with included Jobs  int value; }; // A utility function that is used for sorting events // according to finish time bool jobComparator(Job s1 Job s2) {  return (s1.finish < s2.finish); } // A Binary Search based function to find the latest job // (before current job) that doesn't conflict with current // job. 'index' is index of the current job. This function // returns -1 if all jobs before index conflict with it. The // array jobs[] is sorted in increasing order of finish time int latestNonConflict(Job jobs[] int index) {  // Initialize 'lo' and 'hi' for Binary Search  int lo = 0 hi = index - 1;  // Perform binary Search iteratively  while (lo <= hi)  {  int mid = (lo + hi) / 2;  if (jobs[mid].finish <= jobs[index].start)  {  if (jobs[mid + 1].finish <= jobs[index].start)  lo = mid + 1;  else  return mid;  }  else  hi = mid - 1;  }  return -1; } // The main function that finds the subset of jobs // associated with maximum profit such that no two // jobs in the subset overlap. int findMaxProfit(Job arr[] int n) {  // Sort jobs according to finish time  sort(arr arr + n jobComparator);  // Create an array to store solutions of subproblems.  // DP[i] stores the Jobs involved and their total profit  // till arr[i] (including arr[i])  weightedJob DP[n];  // initialize DP[0] to arr[0]  DP[0].value = arr[0].profit;  DP[0].job.push_back(arr[0]);  // Fill entries in DP[] using recursive property  for (int i = 1; i < n; i++)  {  // Find profit including the current job  int inclProf = arr[i].profit;  int l = latestNonConflict(arr i);  if (l != - 1)  inclProf += DP[l].value;  // Store maximum of including and excluding  if (inclProf > DP[i - 1].value)  {  DP[i].value = inclProf;  // including previous jobs and current job  DP[i].job = DP[l].job;  DP[i].job.push_back(arr[i]);  }  else  // excluding the current job  DP[i] = DP[i - 1];  }  // DP[n - 1] stores the result  cout << 'Optimal Jobs for maximum profits aren' ;  for (int i=0; i<DP[n-1].job.size(); i++)  {  Job j = DP[n-1].job[i];  cout << '(' << j.start << ' ' << j.finish  << ' ' << j.profit << ')' << endl;  }  cout << 'nTotal Optimal profit is ' << DP[n - 1].value; } // Driver program int main() {  Job arr[] = {{3 5 20} {1 2 50} {6 19 100}  {2 100 200} };  int n = sizeof(arr)/sizeof(arr[0]);  findMaxProfit(arr n);  return 0; } 
Java
// Java program for weighted job scheduling using Dynamic // Programming and Binary Search import java.util.*; public class WeightedJobScheduling { // 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;  } } // to store subset of jobs static class weightedJob {  // vector of Jobs  List<Job> job;  // find profit associated with included Jobs  int value;  public weightedJob() {  job = new ArrayList<>();  } } // A utility function that is used for sorting events // according to finish time static class JobComparator implements Comparator<Job> {  @Override  public int compare(Job j1 Job j2) {  return j1.finish - j2.finish;  } } // A Binary Search based function to find the latest job // (before current job) that doesn't conflict with current // job. 'index' is index of the current job. This function // returns -1 if all jobs before index conflict with it. The // array jobs[] is sorted in increasing order of finish time static int latestNonConflict(Job[] jobs int index) {  // Initialize 'lo' and 'hi' for Binary Search  int lo = 0 hi = index - 1;  // Perform binary Search iteratively  while (lo <= hi) {  int mid = (lo + hi) / 2;  if (jobs[mid].finish <= jobs[index].start) {  if (jobs[mid + 1].finish <= jobs[index].start) {  lo = mid + 1;  } else {  return mid;  }  } else {  hi = mid - 1;  }  }  return -1; } // The main function that finds the subset of jobs // associated with maximum profit such that no two // jobs in the subset overlap. static int findMaxProfit(Job[] arr) {  // Sort jobs according to finish time  Arrays.sort(arr new JobComparator()); // Create an array to store solutions of subproblems.  // DP[i] stores the Jobs involved and their total profit  // till arr[i] (including arr[i])  weightedJob[] DP = new weightedJob[arr.length];  DP[0] = new weightedJob();  // initialize DP[0] to arr[0]  DP[0].value = arr[0].profit;  DP[0].job.add(arr[0]);  // Fill entries in DP[] using recursive property  for (int i = 1; i < arr.length; i++) {  // Find profit including the current job  int inclProf = arr[i].profit;  int l = latestNonConflict(arr i);  if (l != -1) {  inclProf += DP[l].value;  }  // Store maximum of including and excluding  if (inclProf > DP[i - 1].value) {  DP[i] = new weightedJob();  DP[i].value = inclProf;  DP[i].job.addAll(DP[l].job);  DP[i].job.add(arr[i]);  } else {    DP[i] = DP[i - 1];  }  }  // DP[n - 1] stores the result  System.out.println('Optimal Jobs for maximum profits are');  for (Job j : DP[arr.length - 1].job) {  System.out.println('(' + j.start + ' ' + j.finish + ' ' + j.profit + ')');  }  System.out.println('nTotal Optimal profit is ' + DP[arr.length - 1].value);  return DP[arr.length - 1].value; }   // Driver program public static void main(String[] args) {  Job[] arr = { new Job(3 5 20)   new Job(1 2 50)  new Job(6 19 100)   new Job(2 100 200) };  findMaxProfit(arr); } } // This code is contributed by ratiagrawal. 
Python3
from typing import List Tuple def find_max_profit(jobs: List[Tuple[int int int]]) -> int: n = len(jobs) # Sort the jobs in ascending order of their finish times jobs.sort(key=lambda x: x[1]) # Initialize DP array with the first job and its profit as the maximum profit DP = [{'value': jobs[0][2] 'jobs': [jobs[0]]}] # Iterate over the remaining jobs for i in range(1 n): # Find the index of the latest non-conflicting job l = latest_non_conflict(jobs i) # Calculate the profit that can be obtained by including the current job incl_prof = jobs[i][2] if l != -1: incl_prof += DP[l]['value'] # Update DP array with the maximum profit and set of jobs if incl_prof > DP[i - 1]['value']: DP.append({'value': incl_prof 'jobs': DP[l]['jobs'] + [jobs[i]]}) else: DP.append(DP[i - 1]) # Print the optimal set of jobs and the maximum profit obtained print('Optimal Jobs for maximum profits are') for j in DP[-1]['jobs']: print(f'({j[0]} {j[1]} {j[2]})') print(f'nTotal Optimal profit is {DP[-1]['value']}') def latest_non_conflict(jobs: List[Tuple[int int int]] index: int) -> int: lo hi = 0 index - 1 while lo <= hi: mid = (lo + hi) // 2 if jobs[mid][1] <= jobs[index][0]: if jobs[mid + 1][1] <= jobs[index][0]: lo = mid + 1 else: return mid else: hi = mid - 1 return -1 # Test the program with a different set of jobs jobs = [(3 5 20) (1 2 50) (6 19 100) (2 100 200)] find_max_profit(jobs) # This code is contributed by divyansh2212 
C#
using System; using System.Collections.Generic; public class WeightedJobScheduling  {  // A job has start time finish time and profit.  class Job {  public int start finish profit;  public Job(int start int finish int profit)  {  this.start = start;  this.finish = finish;  this.profit = profit;  }  }  // to store subset of jobs  class weightedJob   {  // vector of Jobs  public List<Job> job;  // find profit associated with included Jobs  public int value;  public weightedJob() { job = new List<Job>(); }  }  // A utility function that is used for sorting events  // according to finish time  class JobComparator : IComparer<Job> {  public int Compare(Job j1 Job j2)  {  return j1.finish - j2.finish;  }  }  // A Binary Search based function to find the latest job  // (before current job) that doesn't conflict with  // current job. 'index' is index of the current job.  // This function returns -1 if all jobs before index  // conflict with it. The array jobs[] is sorted in  // increasing order of finish time  static int latestNonConflict(Job[] jobs int index)  {  // Initialize 'lo' and 'hi' for Binary Search  int lo = 0 hi = index - 1;  // Perform binary Search iteratively  while (lo <= hi) {  int mid = (lo + hi) / 2;  if (jobs[mid].finish <= jobs[index].start) {  if (jobs[mid + 1].finish  <= jobs[index].start) {  lo = mid + 1;  }  else {  return mid;  }  }  else {  hi = mid - 1;  }  }  return -1;  }  // The main function that finds the subset of jobs  // associated with maximum profit such that no two  // jobs in the subset overlap.  static int findMaxProfit(Job[] arr)  {  // Sort jobs according to finish time  Array.Sort(arr new JobComparator());  // Create an array to store solutions of  // subproblems. DP[i] stores the Jobs involved and  // their total profit till arr[i] (including arr[i])  weightedJob[] DP = new weightedJob[arr.Length];  DP[0] = new weightedJob();  // initialize DP[0] to arr[0]  DP[0].value = arr[0].profit;  DP[0].job.Add(arr[0]);  // Fill entries in DP[] using recursive property  for (int i = 1; i < arr.Length; i++)   {  // Find profit including the current job  int inclProf = arr[i].profit;  int l = latestNonConflict(arr i);  if (l != -1) {  inclProf += DP[l].value;  }  // Store maximum of including and excluding  if (inclProf > DP[i - 1].value) {  DP[i] = new weightedJob();  DP[i].value = inclProf;  DP[i].job.AddRange(DP[l].job);  DP[i].job.Add(arr[i]);  }  else {  DP[i] = DP[i - 1];  }  }  // DP[n - 1] stores the result  Console.WriteLine(  'Optimal Jobs for maximum profits are');  foreach(Job j in DP[arr.Length - 1].job)  {  Console.WriteLine('(' + j.start + ' '  + j.finish + ' ' + j.profit  + ')');  }  Console.WriteLine('nTotal Optimal profit is '  + DP[arr.Length - 1].value);  return DP[arr.Length - 1].value;  }  // Driver program  static void Main(string[] args)  {  Job[] arr  = { new Job(3 5 20) new Job(1 2 50)  new Job(6 19 100) new Job(2 100 200) };  findMaxProfit(arr);  } } // This code is contributed by lokeshpotta20. 
JavaScript
const findMaxProfit = (jobs) => {  // Store the number of jobs  const n = jobs.length;  // Sort the jobs in ascending order of their finish times  jobs.sort((a b) => a[1] - b[1]);  // Initialize DP array with the first job and its profit as the maximum profit  let DP = [{ value: jobs[0][2] jobs: [jobs[0]] }];  // Iterate over the remaining jobs  for (let i = 1; i < n; i++) {  // Find the index of the latest non-conflicting job  const l = latestNonConflict(jobs i);  // Calculate the profit that can be obtained by including the current job  let inclProf = jobs[i][2];  if (l !== -1) {  inclProf += DP[l].value;  }  // Update DP array with the maximum profit and set of jobs  if (inclProf > DP[i - 1].value) {  DP.push({ value: inclProf jobs: DP[l].jobs.concat([jobs[i]]) });  } else {  DP.push(DP[i - 1]);  }  }  // Print the optimal set of jobs and the maximum profit obtained  console.log('Optimal Jobs for maximum profits are');  for (const j of DP[DP.length - 1].jobs) {  console.log(`(${j[0]} ${j[1]} ${j[2]})`);  }  console.log(`nTotal Optimal profit is ${DP[DP.length - 1].value}`); }; const latestNonConflict = (jobs index) => {  let lo = 0;  let hi = index - 1;  while (lo <= hi) {  const mid = Math.floor((lo + hi) / 2);  if (jobs[mid][1] <= jobs[index][0]) {  if (jobs[mid + 1][1] <= jobs[index][0]) {  lo = mid + 1;  } else {  return mid;  }  } else {  hi = mid - 1;  }  }  return -1; }; // Test the program with a different set of jobs const jobs = [[3 5 20] [1 2 50] [6 19 100] [2 100 200]]; findMaxProfit(jobs); // This code is contributed by unstoppablepandu. 

Výstup
Optimal Jobs for maximum profits are (1 2 50) (2 100 200) Total Optimal profit is 250

Časová zložitosť: O(n log n)
Pomocný priestor: O(n)