백준온라인저지

1516번 게임 개발

wonjjong 2018. 8. 23. 15:47

백준 온라인 저지 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());
		ArrayList vertex[] = 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