코딩테스트/백준

[백준][C++]1516번 게임 개발

윤깡패 2023. 7. 21. 21:22

문제

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

 

1516번: 게임 개발

첫째 줄에 건물의 종류 수 N(1 ≤ N ≤ 500)이 주어진다. 다음 N개의 줄에는 각 건물을 짓는데 걸리는 시간과 그 건물을 짓기 위해 먼저 지어져야 하는 건물들의 번호가 주어진다. 건물의 번호는 1부

www.acmicpc.net

 

 

풀이

위상 정렬(Topology Sort) 알고리즘

 

위상 정렬(Topology Sort) 알고리즘

위상 정렬(Topology Sort) 알고리즘 사이클이 없는 방향 그래프에서 모든 노드를 방향성에 거스르지 않도록 순서대로 나열하는 알고리즘 특징 - 항상 유일한 값으로 정렬되지 않는다. - 사이클이 없

soobin0821.tistory.com

 

 

코드

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  int N;
  cin >> N;

  vector<int> time(N + 1, 0);  // 건물을 짓는 데 걸리는 시간 저장 배열 크기 설정
  vector<int> indegree(N + 1, 0);  // 진입 차수 배열
  vector<vector<int>> outnode(N + 1);  // 건물의 개수만큼 인접 리스트 크기 설정
  for(int i = 1; i <= N; i++)
  {
    cin >> time[i];  // 해당 건물을 짓기 위한 시간

    while(true)
    {
      int pre;
      cin >> pre;
      if(pre == -1)
      {
        break;
      }

      indegree[i]++;  // 진입 차수 데이터 저장
      outnode[pre].push_back(i);  // 인접 리스트 데이터 저장
    }
  }

  queue<int> myqueue;  // 위상 정렬 수행
  vector<int> result(N + 1, 0);
  for(int i = 1; i <= N; i++)
  {
    // 진입 차수 배열의 값이 0인 건물(노드)을 큐에 삽입
    if(indegree[i] == 0)
    {
      myqueue.push(i);
    }
  }

  vector<bool> visited(N + 1, false);
  while(!myqueue.empty())
  {
    int now = myqueue.front();
    myqueue.pop();
    visited[now] = true;

    for(int next : outnode[now])
    {
      if(!visited[next])
      {
        indegree[next]--;
        result[next] = max(result[next], result[now] + time[now]);  // 결과 노드 업데이트

        if(indegree[next] == 0)
        {
          myqueue.push(next);  // 우선순위 큐에 타깃 노드 추가
        }
      }
    }
  }

  for(int i = 1; i <= N;i++)
  {
    result[i] += time[i];
    cout << result[i] << "\n";  // 위상 정렬 결과 출력
  }
  
  return 0;
}

 

 

오답

  • 각 건물을 짓는 데 걸리는 최대 시간 업데이트

: max(현재 건물(노드)에 저장된 최대 시간, 이전 건물(노드)에 저장된 최대 시간 + 현재 건물(노드)의 생산 시간)

 

더보기
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int main() 
{
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  int N;
  cin >> N;
  vector<vector<int>> A;
  vector<int> indegree;  // 진입 차수 배열
  vector<int> selfBuild;
  A.resize(N + 1);
  indegree.resize(N + 1);
  selfBuild.resize(N + 1);
  
  for(int i = 1; i <= N; i++)
  {
    cin >> selfBuild[i];  // 해당 건물을 짓기 위한 시간
    // 인접 리스트 데이터 저장
    while(true)
    {
      int preTemp;
      cin >> preTemp;

      if(preTemp == -1)
      {
        break;
      }
      A[preTemp].push_back(i);
      indegree[i]++;  // 진입 차수 데이터 저장
    }
  }
  queue<int> queue; 
  // 위상 정렬 수행
  for(int i = 1; i <= N; i++)
  {
    if(indegree[i] == 0)
    {
      queue.push(i);
    }
  }
  vector<int> result;
  result.resize(N + 1);

  while(!queue.empty())
  {
    int now = queue.front();
    queue.pop();

    for(int next : A[now])
    {
      indegree[next]--;
      result[next] = max(result[next], result[now] + selfBuild[now]);
      if(indegree[next] == 0)
      {
        queue.push(next);
      }
    }
  }
  for(int i = 1; i <= N; i++)
  {
    cout << result[i] + selfBuild[i] << "\n";
  }
}

 

 

 

 

 

728x90