logo

Зважене планування завдань | Набір 2 (з використанням LIS)

Дано 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:
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.

в попередній повідомлення, яке ми обговорювали про проблему зваженого планування завдань. Ми обговорювали рішення DP, де ми в основному включаємо або виключаємо поточну роботу. У цій публікації обговорюється ще одне цікаве рішення DP, де ми також друкуємо завдання. Ця проблема є різновидом стандартної Найдовша зростаюча підпослідовність (LIS) проблема. Нам потрібні невеликі зміни в розв’язанні проблеми LIS за допомогою динамічного програмування.

Спочатку нам потрібно відсортувати завдання за часом початку. Нехай job[0..n-1] буде масивом завдань після сортування. Ми визначаємо вектор L таким чином, що L[i] сам по собі є вектором, який зберігає зважене планування завдань job[0..i], яке закінчується на job[i]. Тому для індексу i L[i] можна рекурсивно записати як - 

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


Наприклад, розглянемо пари {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}

Вибираємо вектор з найбільшим прибутком. У цьому випадку L[1].

java карта

Нижче наведено реалізацію вищезазначеної ідеї – 

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); 

Вихід
(1 2 50) (2 100 200) 


Ми можемо додатково оптимізувати наведене вище рішення DP, видаливши функцію findSum(). Натомість ми можемо підтримувати інший вектор/масив для зберігання суми максимально можливого прибутку до завдання i.



Часова складність вищезгаданого рішення динамічного програмування є O(n2), де n – кількість робочих місць. 
Допоміжне приміщення використовується програмою, це O(n2).