백준 온라인 저지 1516번 게임 개발
문제 출처 : https://www.acmicpc.net/problem/1516
풀이 과정
이번 문제는 정점들 간에 순서를 가지고 있으므로 위상 정렬을 구현해서 각 건물을 짓는데 걸리는 시간을 구하는 문제입니다.
위상 정렬에 관해서는 조만간 정리해서 포스팅하도록 하겠습니다.
어떤 건물의 시간을 구할 때 그 건물을 짓기 위해 먼저 지어져야 할 건물들은 없을 수도 있고, 한 개가 있을 수도 있고 여러 개가 있을 수도 있습니다. 어떤 건물이 지어지는데 걸리는 시간을 구할 때 우선적으로 지어져야 할 건물이 2개 이상일 경우에는 어떻게 최소시간을 구해야 할까요?
예를 들면 C 건물이 지어지는데 걸리는 시간을 구하려고 할 때 C 건물을 짓기 위해선 A 건물과 B 건물들이 지어져 있어야한다고 가정해보겠습니다.
C 건물을 짓는데 걸리는 시간은 10+25 (A+C), 20+25(B+C)가 있습니다. 최소 시간을 구하기 위해 둘 중 어떤 값으로 답을 갱신해야 할까요? 문제에서 최소 시간을 구하라고 해서 작은 값으로 갱신해서는 안됩니다. C는 A와 B 둘 다 지어져 있어야 하는데 A(10초)가 지어져있다고 해도 B(20초)가 지어져 있지 않기 때문에 C를 지을 수 없기 때문입니다. 따라서 먼저 지어져야하는 건물들이 지어지고 자신의 건물이 건설되기 위해서는 가장 오래 걸리는 시간을 기준으로 계산해야 합니다.
즉 위상 정렬을 구현하고 그 위상 정렬에 의해 구해지는 최대 시간을 구하는것이 문제에서 요구하는 최소 시간이 되겠습니다~
소스코드
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws NumberFormatException, IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); int n = Integer.parseInt(in.readLine()); ArrayListvertex[] = new ArrayList[n + 1]; int dist[] = new int[n + 1]; int degree[] = new int[n + 1]; int ans[] = new int[n + 1]; Queue q = new LinkedList<>(); for (int i = 1; i <= n; i++) vertex[i] = new ArrayList<>(); for (int i = 1; i <= n; i++) { StringTokenizer st = new StringTokenizer(in.readLine()); int d = Integer.parseInt(st.nextToken()); dist[i] = ans[i] = d; int v; while ((v = Integer.parseInt(st.nextToken())) != -1) { vertex[v].add(i); degree[i]++; } } for (int i = 1; i <= n; i++) if (degree[i] == 0) q.add(i); while (!q.isEmpty()) { int here = q.poll(); for (int there : vertex[here]) { ans[there] = Math.max(ans[there], ans[here] + dist[there]); if (--degree[there] == 0) q.add(there); } } for (int i = 1; i <= n; i++) { out.write(ans[i] + "\n"); } out.close(); } }
'백준온라인저지' 카테고리의 다른 글
2420번 사파리월드 (0) | 2018.09.12 |
---|---|
2476번 주사위 게임 (0) | 2018.08.31 |
2503번 숫자 야구 (0) | 2018.08.27 |
1946번 신입사원 (0) | 2018.08.22 |
3053번 택시 기하학 (0) | 2018.08.18 |