Job Sequencing Problem | Set 1 (Greedy Algorithm) - GeeksforGeeks
Given an array of jobs where every job has a deadline and associated profit if the job is finished before the deadline. It is also given that every job takes single unit of time, so the minimum possible deadline for any job is 1. How to maximize total profit if only one job can be scheduled at a time.
http://www.geeksforgeeks.org/job-sequencing-using-disjoint-set-union/
Given an array of jobs where every job has a deadline and associated profit if the job is finished before the deadline. It is also given that every job takes single unit of time, so the minimum possible deadline for any job is 1. How to maximize total profit if only one job can be scheduled at a time.
1) Sort all jobs in decreasing order of profit. 2) Initialize the result sequence as first job in sorted jobs. 3) Do following for remaining n-1 jobs .......a) If the current job can fit in the current result sequence without missing the deadline, add current job to the result. Else ignore the current job.
struct
Job
{
char
id;
// Job Id
int
dead;
// Deadline of job
int
profit;
// Profit if job is over before or on deadline
};
// This function is used for sorting all jobs according to profit
bool
comparison(Job a, Job b)
{
return
(a.profit > b.profit);
}
// Returns minimum number of platforms reqquired
void
printJobScheduling(Job arr[],
int
n)
{
// Sort all jobs according to decreasing order of prfit
sort(arr, arr+n, comparison);
int
result[n];
// To store result (Sequence of jobs)
bool
slot[n];
// To keep track of free time slots
// Initialize all slots to be free
for
(
int
i=0; i<n; i++)
slot[i] =
false
;
// Iterate through all given jobs
for
(
int
i=0; i<n; i++)
{
// Find a free slot for this job (Note that we start
// from the last possible slot)
for
(
int
j=min(n, arr[i].dead)-1; j>=0; j--)
{
// Free slot found
if
(slot[j]==
false
)
{
result[j] = i;
// Add this job to result
slot[j] =
true
;
// Make this slot occupied
break
;
}
}
}
// Print the result
for
(
int
i=0; i<n; i++)
if
(slot[i])
cout << arr[result[i]].id <<
" "
;
}
http://www.geeksforgeeks.org/job-sequencing-using-disjoint-set-union/
The costly operation in the Greedy solution is to assign a free slot for a job. We were traversing each and every slot for a job and assigning the greatest possible time slot(<deadline) which was available.
What does greatest time slot means?
Suppose that a job J1 has a deadline of time t = 5. We assign the greatest time slot which is free and less than the deadline i.e 4-5 for this job. Now another job J2 with deadline of 5 comes in, so the time slot allotted will be 3-4 since 4-5 has already been allotted to job J1.
Suppose that a job J1 has a deadline of time t = 5. We assign the greatest time slot which is free and less than the deadline i.e 4-5 for this job. Now another job J2 with deadline of 5 comes in, so the time slot allotted will be 3-4 since 4-5 has already been allotted to job J1.
Why to assign greatest time slot(free) to a job?
Now we assign the greatest possible time slot since if we assign a time slot even lesser than the available one than there might be some other job which will miss its deadline.
Now we assign the greatest possible time slot since if we assign a time slot even lesser than the available one than there might be some other job which will miss its deadline.
Using Disjoint Set for Job Sequencing
All time slots are individual sets initially. We first find the maximum deadline of all jobs. Let the max deadline be m. We create m+1 individual sets. If a job is assigned a time slot of t where t => 0, then the job is scheduled during [t-1, t]. So a set with value X represents the time slot [X-1, X].
We need to keep track of the greatest time slot available which can be allotted to a given job having deadline. We use the parent array of Disjoint Set Data structures for this purpose. The root of the tree is always the latest available slot. If for a deadline d, there is no slot available, then root would be 0. Below are detailed steps.
All time slots are individual sets initially. We first find the maximum deadline of all jobs. Let the max deadline be m. We create m+1 individual sets. If a job is assigned a time slot of t where t => 0, then the job is scheduled during [t-1, t]. So a set with value X represents the time slot [X-1, X].
We need to keep track of the greatest time slot available which can be allotted to a given job having deadline. We use the parent array of Disjoint Set Data structures for this purpose. The root of the tree is always the latest available slot. If for a deadline d, there is no slot available, then root would be 0. Below are detailed steps.
class
DisjointSet
{
int
parent[];
// Constructor
DisjointSet(
int
n)
{
parent =
new
int
[n +
1
];
// Every node is a parent of itself
for
(
int
i =
0
; i <= n; i++)
parent[i] = i;
}
// Path Compression
int
find(
int
s)
{
/* Make the parent of the nodes in the path
from u--> parent[u] point to parent[u] */
if
(s == parent[s])
return
s;
return
parent[s] = find(parent[s]);
}
// Makes u as parent of v.
void
merge(
int
u,
int
v)
{
//update the greatest available
//free slot to u
parent[v] = u;
}
}
class
Job
implements
Comparator<Job>
{
// Each job has a unique-id, profit and deadline
char
id;
int
deadline, profit;
// Constructors
public
Job() { }
public
Job(
char
id,
int
deadline,
int
profit)
{
this
.id = id;
this
.deadline = deadline;
this
.profit = profit;
}
// Returns the maximum deadline from the set of jobs
public
static
int
findMaxDeadline(ArrayList<Job> arr)
{
int
ans = Integer.MIN_VALUE;
for
(Job temp : arr)
ans = Math.max(temp.deadline, ans);
return
ans;
}
// Prints optimal job sequence
public
static
void
printJobScheduling(ArrayList<Job> arr)
{
// Sort Jobs in descending order on the basis
// of their profit
Collections.sort(arr,
new
Job());
// Find the maximum deadline among all jobs and
// create a disjoint set data structure with
// maxDeadline disjoint sets initially.
int
maxDeadline = findMaxDeadline(arr);
DisjointSet dsu =
new
DisjointSet(maxDeadline);
// Traverse through all the jobs
for
(Job temp : arr)
{
// Find the maximum available free slot for
// this job (corresponding to its deadline)
int
availableSlot = dsu.find(temp.deadline);
// If maximum available free slot is greater
// than 0, then free slot available
if
(availableSlot >
0
)
{
// This slot is taken by this job 'i'
// so we need to update the greatest free
// slot. Note that, in merge, we make
// first parameter as parent of second
// parameter. So future queries for
// availableSlot will return maximum slot
// from set of "availableSlot - 1"
dsu.merge(dsu.find(availableSlot -
1
),
availableSlot);
System.out.print(temp.id +
" "
);
}
}
System.out.println();
}
// Used to sort in descending order on the basis
// of profit for each job
public
int
compare(Job j1, Job j2)
{
return
j1.profit > j2.profit? -
1
:
1
;
}
}
A Simple Solution is to generate all subsets of given set of jobs and check individual subset for feasibility of jobs in that subset. Keep track of maximum profit among all feasible subsets. The time complexity of this solution is exponential.
Read full article from Job Sequencing Problem | Set 1 (Greedy Algorithm) - GeeksforGeeks