https://www.acmicpc.net/problem/1516
1516번: 게임 개발
첫째 줄에 건물의 종류 수 N(1 ≤ N ≤ 500)이 주어진다. 다음 N개의 줄에는 각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어진다. 건물의 번호는 1부
www.acmicpc.net
풀이 과정
건물의 여러 종류와 그 건물을 짓는 데 걸리는 시간, 그리고 건물을 지으려면 먼저 지어야 할 건물이 주어질 때, 각 건물을 짓는데 필요한 최소 시간을 구하는 문제이다.
문제에서 주어진 예시를 그림으로 표현하였다. 1번 건물을 지으려면 10초가 소요된다. 2번 건물을 지으려면 1번 건물이 완성된 이후에 지어야 하니 10 + 10 = 20초가 소요되고, 4번 건물을 지으려면 1번 건물 -> 3번 건물 -> 4번 건물 순으로 지어야 하니 10 + 4 + 4 = 18초가 소요된다.
A라는 건물을 짓는데 필요한 소요 시간은
A를 짓기 위해 먼저 지어야 하는 건물의 소요 시간들의 최대 값 + A를 짓는데 필요한 시간이다.
위의 그림으로 보았을때 Directed Acyclic Graph임을 알 수 있으니 위상 정렬을 시행해준 후, 앞에서 부터 소요시간을 계산하고 뒤의 소요시간을 계산하는 데 사용하는 DP를 시행하면서 문제를 해결할 수 있다.
소스 코드
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int cost[501];
vector<int> directed[501];
vector<int> r_directed[501];
int inDegree[501];
queue<int> Q;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, time, goal, cur;
cin >> N;
for (int i = 1; i < N+1; i++) {
cin >> time;
cost[i] = time;
goal = 0;
while(true) {
cin >> goal;
if (goal == -1) break;
directed[goal].push_back(i);
r_directed[i].push_back(goal);
inDegree[i]++;
}
}
for (int i = 1; i < N+1; i++) {
if (inDegree[i] == 0) Q.push(i);
}
while (!Q.empty()) {
int maxValue = 0;
cur = Q.front(); Q.pop();
for (int i = 0; i < r_directed[cur].size(); i++) {
int prev_cost = cost[r_directed[cur][i]];
if (prev_cost > maxValue) {
maxValue = prev_cost;
}
}
if (!r_directed[cur].empty()) cost[cur] += maxValue;
for (int i = 0; i < directed[cur].size(); i++) {
goal = directed[cur][i];
inDegree[goal]--;
if (inDegree[goal] == 0) {
Q.push(goal);
}
}
}
for (int i = 1; i < N+1; i++) {
cout << cost[i] << '\n';
}
return 0;
}
'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글
백준 1932 - 정수 삼각형 [C++] (0) | 2022.07.14 |
---|---|
백준 1753 - 최단경로 [C++] (0) | 2022.07.13 |
백준 1922 - 네트워크 연결 [C++] (0) | 2022.07.12 |
백준 2252 - 줄 세우기 [C++] (0) | 2022.07.12 |
백준 1717 - 집합의 표현 [C++] (0) | 2022.07.11 |