백준의 ACM Craft(1005) 문제이다.

[ 문제 바로가기 ]


[ 문제풀이 ]

순서가 정해진 건물들을 지을 때, 최종적으로 특정 'W'번 건물을 최소 몇 초 만에 지을 수 있는지 구해야 하는 문제이다.

본인은 이 문제를 "일을 처리하는데 그 순서를 정렬하는 위상정렬" 방식을 이용해서 접근해 보았다.

위상정렬에 대해서 따로 포스팅을 하지 않아서, 간단하게만 위상정렬에 대해서 먼저 알아보자.

위상정렬은 위에서 말했듯이 "일을 처리하는 순서를 결정" 하는 것이다.

이 문제도 마찬가지로, 먼저 지을 수 있는 건물이 있고, 특정 건물을 짓지 않으면 지을 수 없는 건물들이 존재한다.

즉, "건물을 짓는 순서를 결정" 해서 'W'번 건물이 몇 초에 지어지는지만 구하면 되므로 위상정렬을 이용해보았다.


또한, 이 문제는 위상정렬을 하면서 일의 순서를 정하는 과정에서 해당 일을 처리하는데 걸리는 최소시간을 구해야 하기

때문에 "해당 일을 처리하는데 걸리는 최소시간을 저장하는 배열" 을 하나 만들어서 관리해 주었다.

Result_Time[] 이라는 1차원 int형 배열을 사용해 주었다.

Result_Time[a] = b 의 의미는 "a번 건물을 짓는데 걸리는 최소시간은 b초입니다." 를 의미한다.

위상정렬이 동작하는 Queue의 반복문 안에서 위의 배열 값 또한 계속해서 갱신해 주면서 진행하였다.


[ 소스코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
 
#define endl "\n"
#define MAX 1010
using namespace std;
 
int N, K, D, W;
int Time[MAX];
int Result_Time[MAX];
int Entry[MAX];
vector<int> Build[MAX];
 
int Bigger(int A, int B) { if (A > B) return A; return B; }
 
void Initialize()
{
    memset(Time, 0sizeof(Time));
    memset(Result_Time, 0sizeof(Result_Time));
    memset(Entry, 0sizeof(Entry));
    for (int i = 0; i < MAX; i++) Build[i].clear();
}
 
void Input()
{
    cin >> N >> K;
    for (int i = 1; i <= N; i++cin >> Time[i];
    for (int i = 0; i < K; i++)
    {
        int a, b; cin >> a >> b;
        Build[a].push_back(b);
        Entry[b]++;
    }
    cin >> W;
}
 
void Solution()
{
    queue<int> Q;
    for (int i = 1; i <= N; i++)
    {
        if (Entry[i] == 0)
        {
            Q.push(i);
            Result_Time[i] = Time[i];
        }
    }
 
    while (Q.empty() == 0)
    {
        int Cur = Q.front();
        Q.pop();
 
        for (int i = 0; i < Build[Cur].size(); i++)
        {
            int Next = Build[Cur][i];
            Result_Time[Next] = Bigger(Result_Time[Next], Result_Time[Cur] + Time[Next]);
            Entry[Next]--;
 
            if (Entry[Next] == 0) Q.push(Next);
        }
    }
 
    cout << Result_Time[W] << endl;
}
 
void Solve()
{
    int Tc; cin >> Tc;
    for (int T = 1; T <= Tc; T++)
    {
        Initialize();
        Input();
        Solution();
    }
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
//    freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
cs

'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글

[ 백준 1516 ] 게임개발 (C++)  (1) 2020.04.19
[ 백준 1766 ] 문제집 (C++)  (0) 2020.04.17
[ 백준 2252 ] 줄 세우기 (C++)  (0) 2020.04.02
[ 백준 1944 ] 복제로봇 (C++)  (2) 2020.04.01
[ 백준 13302 ] 리조트 (C++)  (0) 2020.03.31

+ Recent posts