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

📅  最后修改于: 2021-09-22 09:58:55             🧑  作者: 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] 的子序列中确定调度的最大值。通过将 job[i] 的包含与计划的包含与 job[i] 的排除与计划的进行比较,然后取最大值来做到这一点。

找到包含 job[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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程