Job Scheduling
Β - Last update: 2023-10-24

Job Scheduling

이 μœ ν˜•μ€ λ¬Έμ œμ—μ„œ μ£Όμ–΄μ§„ 쑰건에 따라 풀이 방법이 맀우 λ‹€μ–‘ν•˜κ²Œ λ‚˜λ‰  수 μžˆλ‹€.

μž‘μ—… 배정을 ν• μ§€ μ•ˆν• μ§€λ§Œ κ²°μ •

// Greedy 기초
// μž‘μ—…μ„ μ§„ν–‰ν•˜λŠ”λ° κ±Έλ¦¬λŠ” μ‹œκ°„ Tκ°€ μ£Όμ–΄μ§€μ§€ μ•Šμ•˜λ‹€.
// κ·Έ μž‘μ—…μ„ 채택할지 μ•ˆν• μ§€λ§Œ 보면 λœλ‹€.
// 1. μ •λ ¬ Phase
// λλ‚˜λŠ” μ‹œκ°„ κΈ°μ€€μœΌλ‘œ μ •λ ¬ν•œλ‹€.
// 2. ν• λ‹Ή Phase
// μ•žμ—μ„œλΆ€ν„° μ°¨λ‘€λŒ€λ‘œ ν• λ‹Ήν•œλ‹€.
struct Meeting {
int s, e;
};
void solve(vector<Meeting>& v) {
sort(v.begin(), v.end(), [&](Meeting& a, Meeting& b) -> bool {
if (a.e != b.e) return a.e < b.e;
return a.s < b.s;
});
int last = 0;
int ans = 0;
for(auto& item: v) {
if (item.s >= last) ++ans, last = item.e;
}
printf("%d\n", ans);
}

μž‘μ—… λμ‹œκ°„(Deadline)κ³Ό μˆ˜ν–‰ν•˜λŠ” 데 κ±Έλ¦¬λŠ” μ‹œκ°„(T)κ°€ μ£Όμ–΄μ§„ 경우

struct Job {
int t;
int d; // deadline
bool operator<(const Job& t) const {
if (d != t.d) return d > t.d;
return this->t < t.t;
}
};
void solve(vector<Job>& v) {
sort(v.begin(), v.end());
int ctime = v[0].d - v[0].t;
for(int i = 1; i < v.size(); ++i) {
ctime = min(ctime, v[i].d); // backward scheduling
ctime -= v[i].t;
}
if (ctime < 0) printf("-1\n");
else printf("%d\n", ctime);
}

μž‘μ—… μˆ˜ν–‰ μ‹œκ°„μ΄ T = 1인 경우

// 기본적으둜 μ‹œκ°„μ„ 1λΆ€ν„° λκΉŒμ§€ ν›‘μœΌλ©΄μ„œ ν• λ‹Ήν•˜λŠ” 것
// λ‹€λ§Œ, 더 이상 후보ꡰ이 없을 λ•ŒλŠ” 기둝이 μžˆλŠ” 지점뢀터 λ‹€μ‹œ μ‹œμž‘
// -> μ΄λ ‡κ²Œ μ•ˆν•˜λ©΄ ꡬ간 클 경우 TLE
// 과정을 λ‹€μ‹œ μš”μ•½ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€. (time에 λŒ€ν•œ sliding window 기법)
// 1. κ°€μž₯ r_iκ°€ μž‘μ€ μ‹œκ°„ μž‘μ—…λΆ€ν„° μ‹œμž‘
// 1-1. r_i와 같은 μ‹œκ°„μ— μ‹œμž‘ν•˜λŠ” μž‘μ—…λ“€μ€ λͺ¨λ‘ pq에 λ„£λŠ”λ‹€.
// 2. κ·Έ 쀑 d_iκ°€ κ°€μž₯ 짧은 녀석뢀터 μ‹œκ°„μ„ 1μ”© μ¦κ°€μ‹œμΌœκ°€λ©΄μ„œ μ‹€μ œλ‘œ ν• λ‹Ήν•œλ‹€.
// 2-1. ν• λ‹Ήν•  λ•Œ ν•œλ²ˆμ— λ‹€ ν•˜λŠ”κ²Œ μ•„λ‹ˆλΌ, ν˜„μž¬ μ‹œκ°„μ— 1개만 ν• λ‹Ήν•˜κ³ , λ‹€μŒ μ‹œκ°„μ„ μ—°μ†ν•΄μ„œ λ³΄λ©΄μ„œ ν• λ‹Ήν•œλ‹€.
// 3. λ§Œμ•½ λ³΄λ €λŠ” 녀석이 이미 λ³΄κ³ μžˆλŠ” μ‹œκ°„λŒ€λ₯Ό μ§€λ‚˜κ°”λ‹€λ©΄ 버린닀.
void solve(map<ll, priority_queue<ll, vector<ll>, greater<>>>& M) {
// M[a] = {1, 2, 3} - a μ‹œκ°„μ— μ‹œμž‘ν•˜λŠ” 일이 1, 2, 3에 λλ‚˜λŠ” 3κ°€μ§€κ°€ μžˆλ‹€.
int ans = 0;
// unit time: 1μž„
ll ctime = 0;
priority_queue<ll, vector<ll>, greater<>> gpq; // global pq
auto it = M.begin();
for(ll ctime = 1; ; ++ctime) { // μ‹œκ°„μ„ μ¦κ°€μ‹œμΌœκ°€λ©΄μ„œ λ³Έλ‹€.
if (gpq.size() == 0) {
// 아무것도 μ—†μœΌλ‹ˆ λ‚΄λ§˜λŒ€λ‘œ μ‹œκ°„μ„ λ§žμΆ˜λ‹€~
if (it == M.end()) break;
auto& cur = *it;
ctime = cur.first;
++it;
}
if (M.find(ctime) != M.end()) {
it = M.find(ctime);
auto& cur = *it;
auto& pq = cur.second;
while(pq.size()) gpq.push(pq.top()), pq.pop();
++it;
}
// μœ νš¨ν•˜μ§€ μ•Šμ€ gpq 값을 κΊΌλ‚Έλ‹€.
while (gpq.size() && gpq.top() < ctime) gpq.pop();
// pqμ—μ„œ κ°€μž₯ μž‘μ€κ±° ν•˜λ‚˜ κΊΌλ‚΄μ„œ μ“΄λ‹€.
if (gpq.size()) {
gpq.pop();
++ans;
}
}
printf("%d\n", ans);
}

Release Time, Deadline 이 μ‘΄μž¬ν•˜λ©°, μ£Όμ–΄μ§„ νŠΉμ • μ‹œκ°„μ—λ§Œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” μœ ν˜•

  • μ†Œκ°€ 길을 κ±΄λ„ˆκ°„ 이유 4 문제: https://www.acmicpc.net/problem/14464
  • μœ„ μœ ν˜•μ˜ μ—΄ν™”νŒ.
    • Release Time이 λΉ λ₯Έ 녀석뢀터 λ³΄λ©΄μ„œ Deadline을 PQ에 μ €μž₯ν•˜λŠ” κ²ƒκΉŒμ§€λŠ” λ˜‘κ°™μ€λ°, νŠΉμ • μ‹œκ°„μ—λ§Œ μž‘μ—…μž‰ μˆ˜ν–‰μ΄ κ°€λŠ₯ν•˜λ‹€λŠ” 것은 νŠΉμ • μ‹œκ°„λ§Œ 보면 λœλ‹€λŠ” 의미이고, νŠΉμ • μ‹œκ°„μ„ μˆœνšŒν•˜λ©΄μ„œ μ²΄ν¬ν•˜λ©΄ λœλ‹€.
void solve(vector<int>& chicken, vector<pair<int,int>>& cow, int N, int M) {
sort(cow.begin(), cow.end());
sort(chicken.begin(), chicken.end());
// deadline을 μˆœμ„œλŒ€λ‘œ λ„£μž. ν˜„μž¬ μœ νš¨ν•œ λ…€μ„λ“€λ§Œ λ“€μ–΄κ°€ 있게 λœλ‹€.
priority_queue<int, vector<int>, greater<>> pq;
int cowPtr = 0;
int ans = 0;
for(auto& c: chicken) {
int cur = c; // ν˜„μž¬ λ³΄λŠ” chicken의 T_i
for(; cowPtr < M; ++cowPtr) {
if (cow[cowPtr].y < cur) continue; // 버린닀. 이미 λ‹€ μ§€λ‚˜κ°”λ‹€.
if (cow[cowPtr].x <= cur && cur <= cow[cowPtr].y) {
pq.push(cow[cowPtr].y); // deadline μˆœμ„œλ‘œ μ •λ ¬ν•˜λŠ” pq에 λ„£κΈ°.
} else {
// μ•žμœΌλ‘œ μ“Έ 녀석듀을 λ§Œλ‚¬λ‹€. 더이상 pq에 λ„£μ§€μ•Šκ³  μ’…λ£Œ
break;
}
}
while(pq.size() && pq.top() < cur) pq.pop(); // μœ νš¨ν•˜μ§€ μ•Šμ€κ²ƒ 버리기
if (pq.size()) {
// printf("[d] deadline: %d / chicken: %d matched!\n", pq.top(), cur);
pq.pop();
++ans;
}
}
printf("%d\n", ans);
}

μ „λΆ€ ν• λ‹Ήν•΄μ•Όν•  λ•Œ ν•„μš”ν•œ μ΅œμ†Œ κΈ°κ³„μ˜ 수λ₯Ό κ³„μ‚°ν•˜λŠ” μœ ν˜•

struct Range {
int l, r;
bool operator<(const Range& t) {
if (l != t.l) return l < t.l;
return r < t.r;
}
};
void solve(vector<Range>& v) {
sort(v.begin(), v.end()); // 빨리 μ‹œμž‘ν•˜λŠ” μˆœμ„œλŒ€λ‘œ μ •λ ¬
priority_queue<int, vector<int>, greater<>> pq;
for(auto& item: v) {
if (pq.size() == 0) {
pq.push(item.r);
continue;
}
if (item.l >= pq.top()) { // 일단 λ“€μ–΄κ°ˆ 수 μžˆλ‹€.
pq.pop();
pq.push(item.r); // κΈ°μ‘΄ 녀석을 λŒ€μ²΄
} else { // λͺ»λ“€μ–΄κ°€λŠ” case이닀. (ν˜„μž¬ κ°€μž₯ 빨리 λλ‚˜λŠ” 녀석보닀도 μ‹œμž‘μ΄ 빠름)
pq.push(item.r);
}
}
printf("%ld\n", pq.size());
}

Time Complexity

  • μš°μ„  μˆœμœ„ 큐 베이슀 μ•Œκ³ λ¦¬μ¦˜μ΄κΈ° λ•Œλ¬Έμ— λͺ¨λ‘ O(Nlog⁑N)O(N\log N)