본문 바로가기
Problem Solving

[BOJ 1516] 게임 개발

by Ladun 2020. 4. 20.

https://www.acmicpc.net/problem/1516

 

1516번: 게임 개발

첫째 줄에 건물의 종류 수 N(1 ≤ N ≤ 500)이 주어진다. 다음 N개의 줄에는 각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어진다. 건물의 번호는 1부터 N까지로 하고, 각 줄은 -1로 끝난다고 하자. 각 건물을 짓는데 걸리는 시간은 100,000보다 작거나 같은 자연수이다.

www.acmicpc.net


위 문제는 위상 정렬을 이용하여 푸는 문제이다.

 

위상 정렬이란 그래프에서 진입 차수가 0인 노드를 차례대로 제거해나가는 형식의 정렬이다.

 

진입 차수가 0이 되는 순서대로 출력을 하는것이다. 

 

위 문제에 대입해보자면, 어떤 건물을 짓기 위해 지어야하는 건물들의 관계를 그래프로 그려보면, 어떤 건물을 짓기 위해 먼저 지어야하는 건물의 수가 진입차수가 되게 된다.

 

위 문제의 예제를 그래프로 그려보면 아래와 같이 된다.

위 그래프에서 진입 차수가 0인걸 차례대로 제거해나가면서 건물이 지어지는 시간을 갱신하면 된다.

 

4번 건물의 경우 1번, 3번 건물이 지어져야 지어지는데, 3번 건물은 1번 건물이 지어져야 건설이 가능하니

1 -> 3 -> 4번 순으로 건물을 건설하면 총 18이라는 시간이 소모된다. 


#include <stdio.h>
#include <vector>
#include <queue>

using namespace std;

int n;
vector<vector<int>> g;
pair<int, int> gInfo[501];
int ans[501];

int main()
{
	scanf("%d", &n);
	g.resize(n + 1);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &gInfo[i].first);
		while (1)
		{
			int t;
			scanf("%d", &t);
			if (t == -1)
				break;

			g[t].push_back(i);
			gInfo[i].second++;
		}
	}

	queue<int> q;

	for (int i = 1; i <= n; i++)
	{
		if (gInfo[i].second == 0)
		{
			q.push(i);
		}
		ans[i] = gInfo[i].first;
	}

	while (!q.empty())
	{
		int p = q.front(); q.pop();

		for (auto s = g[p].begin(); s != g[p].end(); s++)
		{
			if (--gInfo[*s].second == 0)
				q.push(*s);
			ans[*s] = max(ans[*s], gInfo[*s].first + ans[p]);
		}
	}

	for (int i = 1; i <= n; i++)
	{
		printf("%d\n", ans[i]);
	}
}

'Problem Solving' 카테고리의 다른 글

[BOJ 2252] 줄 세우기  (0) 2020.04.20
[BOJ 1005] ACM Craft  (0) 2020.04.20
[BOJ 1806] 부분합  (0) 2020.04.17
[BOJ 13398] 연속합 2  (0) 2020.04.17
[BOJ 1717] 집합의 표현  (0) 2020.04.08