알고리즘/위상 정렬
위상 정렬 - 게임 개발하기
sim0609
2023. 5. 13. 23:36
<문제>
백준 - 1516: 게임 개발하기
https://www.acmicpc.net/problem/1516
1516번: 게임 개발
첫째 줄에 건물의 종류 수 N(1 ≤ N ≤ 500)이 주어진다. 다음 N개의 줄에는 각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어진다. 건물의 번호는 1부
www.acmicpc.net
<문제 접근>
2차원 벡터를 생성해 각 건물마다 먼저 지어야할 건물에 대한 정보를 입력한 후 BFS를 이용해 각 건물의 건축 시간을 계산하는 방식으로 접근했다.
<슈도 코드>
→ 문제를 풀면서 기존 슈도코드와 많이 달라져 실패한 코드 올림
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector <vector<int>> v;
vector <vector<int>> v_build;
vector <int> cost;
vector <int> re_cost;
vector <int> visited;
queue <int> q;
int n;
void cal_cost(int b);
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int value;
cin >> n;
cost.resize(n + 1);
re_cost.resize(n + 1, 0);
v.resize(n + 1);
visited.resize(n + 1, 0);
v_build.resize(n + 1);
for (int i = 1; i <= n; i++) {
for (int j = 0; j < n; j++) {
cin >> value;
if (value == -1) {
break;
}
else {
v[i].push_back(value);
}
}
}
for (int i = 1; i <= n; i++) {
cost[i] = v[i][0];
}
for (int i = 1; i <= n; i++) {
v_build[i].push_back(i);
for(int j = 1; j < v[i].size(); j++) {
v_build[i].push_back(v[i][j]);
}
}
for (int i = 1; i <= n; i++) {
cal_cost(i);
fill(visited.begin(), visited.end(), 0);
}
for (int i = 1; i <= n; i++) {
cout << re_cost[i] << endl;
}
}
void cal_cost(int b) {
q.push(b);
visited[b] = 1;
re_cost[b] += cost[b];
while (!q.empty()) {
int f = q.front();
q.pop();
for (int i = 0; i < v_build[f].size(); i++) {
if (visited[v_build[f][i]] == 0) {
q.push(v_build[f][i]);
re_cost[b] += cost[v_build[f][i]];
visited[v_build[f][i]] = 1;
}
}
}
}
<코드>
→ 위상정렬의 진입차수 계산 방식을 이용해 문제에 접근해야 해결됨
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int n;
vector<vector<int>> A;
vector<int> indegree;
vector<int> selfbuild;
vector<int> cost;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int node;
cin >> n;
A.resize(n + 1);
indegree.resize(n + 1);
selfbuild.resize(n + 1, 0);
cost.resize(n + 1, 0);
for (int i = 1; i <= n; i++) {
cin >> selfbuild[i]; // 해당 건물을 짓기 위한 시간
for (int j = 0; j < n; j++) {
cin >> node;
if (node == -1) {
break;
}
else {
A[node].push_back(i);
indegree[i]++; // 진입 차수 저장
}
}
}
queue<int> q;
// 위상 정렬 수행
for (int i = 1; i <= n; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int f = q.front();
q.pop();
for (int i = 0; i < A[f].size(); i++) {
cost[A[f][i]] = max(cost[A[f][i]], cost[f] + selfbuild[f]);
indegree[A[f][i]]--;
if (indegree[A[f][i]] == 0) {
q.push(A[f][i]);
}
}
}
for (int i = 1; i <= n; i++) {
cout << cost[i] + selfbuild[i] << endl;
}
}