📜  O(n Log n)时间的加权作业调度

📅  最后修改于: 2021-05-04 14:33:53             🧑  作者: Mango

给定N个工作,其中每个工作都由以下三个元素表示。

  1. 开始时间
  2. 结束时间
  3. 关联的利润或价值

找到作业的最大利润子集,以使子集中的两个作业没有重叠。

例子:

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: The maximum profit is 250.
We can get the maximum profit by scheduling jobs 1 and 4.
Note that there is longer schedules possible Jobs 1, 2 and 3 
but the profit with this schedule is 20+50+100 which is less than 250.  

我们强烈建议您参考以下文章作为此操作的先决条件。
加权作业计划

可以使用以下递归解决方案来解决上述问题。

1) First sort jobs according to finish time.
2) Now apply following recursive process. 
   // Here arr[] is array of n jobs
   findMaximumProfit(arr[], n)
   {
     a) if (n == 1) return arr[0];
     b) Return the maximum of following two profits.
         (i) Maximum profit by excluding current job, i.e., 
             findMaximumProfit(arr, n-1)
         (ii) Maximum profit by including the current job            
   }

How to find the profit including current job?
The idea is to find the latest job before the current job (in 
sorted array) that doesn't conflict with current job 'arr[n-1]'. 
Once we find such a job, we recur for all jobs till that job and
add profit of current job to result.
In the above example, "job 1" is the latest non-conflicting
for "job 4" and "job 2" is the latest non-conflicting for "job 3".

在上一篇文章中,我们讨论了基于递归和动态编程的方法。以上文章中讨论的实现使用线性搜索来找到先前的非冲突作业。在这篇文章中,讨论了基于二进制搜索的解决方案。基于二进制搜索的解决方案的时间复杂度为O(n Log n)。

该算法是:

  1. 按不减少的完成时间对作业进行排序。
  2. 对于从1到n的每个i,从作业[0..i]的子序列确定时间表的最大值。为此,可将作业[i]包含在计划中,将作业[i]包含在计划中,然后取最大值。

寻找包含工作的利润[i]。我们需要找到与job [i]不冲突的最新工作。想法是使用二进制搜索来找到最新的不冲突的作业。

C/C++
// C++ program for weighted job scheduling using Dynamic 
// Programming and Binary Search
#include 
#include 
using namespace std;
  
// A job has start time, finish time and profit.
struct Job
{
    int start, finish, profit;
};
  
// A utility function that is used for sorting events
// according to finish time
bool myfunction(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 binarySearch(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 returns the maximum possible
// profit from given array of jobs
int findMaxProfit(Job arr[], int n)
{
    // Sort jobs according to finish time
    sort(arr, arr+n, myfunction);
  
    // Create an array to store solutions of subproblems.  table[i]
    // stores the profit for jobs till arr[i] (including arr[i])
    int *table = new int[n];
    table[0] = arr[0].profit;
  
    // Fill entries in table[] using recursive property
    for (int i=1; i


Python
# Python program for weighted job scheduling using Dynamic 
# Programming and Binary Search
  
# Class to represent a job
class Job:
    def __init__(self, start, finish, profit):
        self.start  = start
        self.finish = finish
        self.profit  = profit
  
  
# 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.
def binarySearch(job, start_index):
  
    # Initialize 'lo' and 'hi' for Binary Search
    lo = 0
    hi = start_index - 1
  
    # Perform binary Search iteratively
    while lo <= hi:
        mid = (lo + hi) // 2
        if job[mid].finish <= job[start_index].start:
            if job[mid + 1].finish <= job[start_index].start:
                lo = mid + 1
            else:
                return mid
        else:
            hi = mid - 1
    return -1
  
# The main function that returns the maximum possible
# profit from given array of jobs
def schedule(job):
    
    # Sort jobs according to finish time
    job = sorted(job, key = lambda j: j.finish)
  
    # Create an array to store solutions of subproblems.  table[i]
    # stores the profit for jobs till arr[i] (including arr[i])
    n = len(job) 
    table = [0 for _ in range(n)]
  
    table[0] = job[0].profit;
  
    # Fill entries in table[] using recursive property
    for i in range(1, n):
  
        # Find profit including the current job
        inclProf = job[i].profit
        l = binarySearch(job, i)
        if (l != -1):
            inclProf += table[l];
  
        # Store maximum of including and excluding
        table[i] = max(inclProf, table[i - 1])
  
    return table[n-1]
  
# Driver code to test above function
job = [Job(1, 2, 50), Job(3, 5, 20), 
      Job(6, 19, 100), Job(2, 100, 200)]
print("Optimal profit is"),
print schedule(job)


Java
// Java program for Weighted Job Scheduling in O(nLogn)
// time
import java.util.Arrays;
import java.util.Comparator;
  
// Class to represent a job
class Job
{
    int start, finish, profit;
  
    // Constructor
    Job(int start, int finish, int profit)
    {
        this.start = start;
        this.finish = finish;
        this.profit = profit;
    }
}
  
// Used to sort job according to finish times
class JobComparator implements Comparator
{
    public int compare(Job a, Job b)
    {
        return a.finish < b.finish ? -1 : a.finish == b.finish ? 0 : 1;
    }
}
  
public class WeightedIntervalScheduling
{
    /* 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 public int binarySearch(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 returns the maximum possible
    // profit from given array of jobs
    static public int schedule(Job jobs[])
    {
        // Sort jobs according to finish time
        Arrays.sort(jobs, new JobComparator());
  
        // Create an array to store solutions of subproblems.
        // table[i] stores the profit for jobs till jobs[i]
        // (including jobs[i])
        int n = jobs.length;
        int table[] = new int[n];
        table[0] = jobs[0].profit;
  
        // Fill entries in M[] using recursive property
        for (int i=1; i


输出:

Optimal profit is 250