Job Sequencing & Scheduling Algorithms
1. Algorithm & Complexity
The classic Job Sequencing with Deadlines problem is: Given N jobs, each with a deadline and a profit, schedule at most one job per time slot so as to maximize total profit (each job takes unit time). The standard greedy solution:
- Sort all jobs in descending order of profit.
- Create an array
slot[1…maxDeadline]
, initialized to –1 (empty). - For each job in sorted order:
- Try to schedule it in the latest free slot ≤ its deadline (scan from
d
down to 1). - If you find an empty slot, assign the job there and add its profit.
- Try to schedule it in the latest free slot ≤ its deadline (scan from
- Remaining slots stay empty.
Time Complexity
Let D = maximum deadline among all jobs.
- Sorting takes O(N log N).
- For each of N jobs, we scan up to D slots → O(N·D).
Memory Complexity
- Store N jobs → O(N).
- Slot array of size D → O(D).
2. Easy Examples
2.1 – Codeforces 1203F1 “Complete Projects (easy version)”
Given N projects, each with a duration tᵢ
and a deadline dᵢ
, you can do at most one project at a time.
Maximize the number of completed projects.
Here each project takes tᵢ
time, deadline is the latest finish time.
Input: 3 3 2 1 2 2 2 Output: 2
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
vector<pair<,int>> projects(N);
for (int i = 0; i < N; i++)
cin >> projects[i].first >> projects[i].second;
// sort by deadline
sort(projects.begin(), projects.end(),
[] (auto &a, auto &b) { return a.second < b.second; });
int currTime = 0, count = 0;
for (auto &p : projects) {
if (currTime + p.first <= p.second) {
currTime += p.first;
count++;
}
}
cout << count << "\n";
return 0;
}
2.2 – Codeforces 1592E “Tasks and Deadlines”
Given N tasks with duration tᵢ
and deadline dᵢ
, you must perform all tasks in some order.
Compute the total “lateness penalty” = ∑|finishᵢ − dᵢ|.
Greedy: sort by duration ascending (shortest‐processing‐time first).
Input: 3 3 5 1 2 2 4 Output: 3
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
vector<pair<,int>> tasks(N);
for (int i = 0; i < N; i++)
cin >> tasks[i].first >> tasks[i].second;
// Sort by duration
sort(tasks.begin(), tasks.end(),
[] (auto &a, auto &b) { return a.first < b.first; });
long long time = 0, penalty = 0;
for (auto &t : tasks) {
time += t.first;
penalty += llabs(time - t.second);
}
cout << penalty << "\n";
return 0;
}
3. Intermediate Examples
3.1 – Codeforces 1203F2 “Complete Projects (hard version)”
Same as F1, but N ≤ 2·10⁵, durations and deadlines large. Use a max‐heap to drop the longest project when current time exceeds deadline.
Input: 5 4 4 3 4 2 3 1 2 5 6 Output: 4
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main(){
int N;
cin >> N;
vector<pair<,int>> proj(N);
for(int i=0;i<N;i++) cin >> proj[i].first >> proj[i].second;
sort(proj.begin(), proj.end(),
[] (auto &a, auto &b){ return a.second < b.second; });
priority_queue<int> pq;
long long time = 0;
for (auto &p : proj) {
time += p.first;
pq.push(p.first);
if (time > p.second) {
time -= pq.top();
pq.pop();
}
}
cout << (int)pq.size() << "\n";
return 0;
}
3.2 – Codeforces 1635C “Schedule the Exams”
Given M exams each with a day and duration, decide if you can schedule all so no two overlap (unit‐slot scheduling). Sort by day, assign earliest possible slot.
Input: 4 3 1 2 2 1 3 1 1 1 Output: YES
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int M, D;
cin >> M >> D;
vector<pair<,int>> exams(M);
for(int i=0;i<M;i++) cin >> exams[i].first >> exams[i].second;
sort(exams.begin(), exams.end());
int day = 1;
for (auto &e : exams) {
if (day + e.second - 1 > D || day > e.first) {
cout << "NO\n";
return 0;
}
day += e.second;
}
cout << "YES\n";
return 0;
}
4. Hard Example
4.1 – Codeforces 1490E “Job Sequencing (classic)”
Given N jobs with deadlines and profits (unit time), maximize profit. This is the classic greedy with slot‐array approach.
Input: 5 Job1 2 100 Job2 1 19 Job3 2 27 Job4 1 25 Job5 3 15 Output: 142
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Job { string id; int dl, profit; };
int main(){
int N;
cin >> N;
vector<Job> jobs(N);
int maxD = 0;
for(int i=0;i<N;i++){
cin >> jobs[i].id >> jobs[i].dl >> jobs[i].profit;
maxD = max(maxD, jobs[i].dl);
}
sort(jobs.begin(), jobs.end(),
[] (auto &a, auto &b){ return a.profit > b.profit; });
vector<bool> slot(maxD+1,false);
int total = 0;
for (auto &j : jobs) {
for (int t = j.dl; t > 0; --t) {
if (!slot[t]) {
slot[t] = true;
total += j.profit;
break;
}
}
}
cout << total << "\n";
return 0;
}