반응형
문제 링크: https://www.acmicpc.net/problem/2056
2056번: 작업
수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해
www.acmicpc.net
<문제 풀이> 다이나믹 프로그래밍(DP), 위상정렬 알고리즘
작업에는 순서가 있으므로 위상정렬을 사용해야 합니다. 또한, 모든 작업을 완료하기 위한 최소 시간을 구하기 위해 DP를 활용해야 합니다.
DP의 정의는 아래와 같습니다:
DP[i] : i번째 작업이 완료되는 데 필요한 최소 시간
위상 정렬을 수행하며 현재 작업에 연결된 다음 작업들의 최소 완료 시간을 갱신해 나갑니다. 현재 작업을'cur', 그에 연결된 다음 작업을 'next'라고 할 때, 'next'작업의 최소 완료 시간은 아래와 같이 계산합니다:
dp[next] = max(dp[next], dp[cur] + t[next]);
여기서 max함수를 사용하는 이유는 다음 작업에 대한 선행 작업들 중에서 최소 완료 시간이 가장 긴 작업이 그 작업의 완료 시간에 영향을 주기 때문입니다.
예를 들어, A 작업이 5분, C 작업이 3분이 걸린다고 할 때, B 작업을 시작하기 위해선 A작업이 완료되어야 합니다.
A(5분) -> B
B(3분) -> B
<C++소스코드>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
vector<int> adj[10001];
int indegree[10001];
int t[10001];
int dp[10001];
int main(void) {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int n; cin >> n;
for (int u = 1; u <= n; u++) {
cin >> t[u];
int m; cin >> m;
while (m--) {
int v; cin >> v;
adj[v].push_back(u);
indegree[u]++;
}
}
queue<int> Q;
for (int u = 1; u <= n; u++){
if (indegree[u] == 0) {
Q.push(u);
dp[u] = t[u];
}
}
while (!Q.empty()) {
auto cur = Q.front(); Q.pop();
for (auto next : adj[cur]) {
indegree[next]--;
dp[next] = max(dp[next], dp[cur] + t[next]);
if (indegree[next] == 0) {
Q.push(next);
}
}
}
cout << *max_element(dp + 1, dp + 1 + n);
return 0;
}
반응형
'알고리즘 문제풀이 > 백준' 카테고리의 다른 글
[백준 5719번] 거의 최단 경로 (0) | 2023.09.18 |
---|---|
[백준 1774번] 우주신과의 교감 (0) | 2023.09.10 |
[백준 2283] 구간 자르기 (0) | 2023.08.30 |
[백준 17521번] Byte Coin (0) | 2023.04.24 |
[백준 1439번] 뒤집기 (0) | 2023.04.23 |