본문 바로가기
삼성 코팅테스트 준비/모의 역량 테스트 문제

해결) 5653 줄기세포 배양

by tryotto 2020. 3. 7.

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
 
using namespace std;
 
// 변수
int height, width, total_time;
int flag[700][700];
int dx[4= { 00-11 };
int dy[4= { 1-100 };
int cen_x = 400, cen_y = 400;
 
// 비교 연산 클래스
class cmp {
public:
    bool operator()(pair<pair<intint>pair<intint> > a, pair<pair<intint>pair<intint> > b) {
        int tmp1 = a.second.second;
        int tmp2 = b.second.second;
 
        if (tmp1 < tmp2)
            return true;
        else
            return false;
    }
};
 
// 우선순위 큐
queue<pair<pair<intint>pair<intint> > > pq;
// 우선순위 큐 2 - tmp_pq
priority_queue<pair<pair<intint>pair<intint> >,
    vector<pair<pair<intint>pair<intint> > >, cmp> tmp_pq;
 
// 함수 모음
void initialize();
void time_pass();
 
// 함수들
int main() {
    int test;
    scanf("%d"&test);
 
    for (int t = 1; t <= test; t++) {
        initialize();
 
        for (int i = 0; i < total_time; i++
            time_pass();
 
        printf("#%d %d\n", t, pq.size());    
    }
}
 
void time_pass() {
    while (!pq.empty()) {
        // 우선순위 큐 추출
        int y = pq.front().first.first;
        int x = pq.front().first.second;
        int t_cnt = pq.front().second.first;
        int power = pq.front().second.second;
 
        pq.pop();
 
        // t_cnt 증가
        t_cnt++;
 
        // 비활성화 -> 활성화 전환
        if (t_cnt == power) 
            tmp_pq.push(make_pair(make_pair(y, x), make_pair(t_cnt, power)));        
        // 활성화 전이
        else if ((t_cnt > power) && (t_cnt <= 2 * power)) {
            for (int i = 0; i < 4; i++) {
                int xx = x + dx[i];
                int yy = y + dy[i];
 
                if (flag[yy][xx] == 0)
                    tmp_pq.push(make_pair(make_pair(yy, xx), make_pair(0, power)));
            }
            if (t_cnt != 2 * power)
                tmp_pq.push(make_pair(make_pair(y, x), make_pair(t_cnt, power)));
            if (t_cnt == 2 * power)
                flag[y][x] = -power;                
        }
        // 비활성화 유지
        else if (t_cnt < power) 
            tmp_pq.push(make_pair(make_pair(y, x), make_pair(t_cnt, power)));        
    }
 
    while (!tmp_pq.empty()) {
        // 우선순위 큐 추출
        int y = tmp_pq.top().first.first;
        int x = tmp_pq.top().first.second;
        int t_cnt = tmp_pq.top().second.first;
        int power = tmp_pq.top().second.second;
 
        tmp_pq.pop();
 
        if (t_cnt == 0) {
            // 비어있는 셀일 경우, 전이
            if (flag[y][x] == 0) {
                flag[y][x] = power;        
                pq.push(make_pair(make_pair(y, x), make_pair(0, power)));
            }
        }
        else 
            pq.push(make_pair(make_pair(y, x), make_pair(t_cnt, power)));
        
    }
}
 
void initialize() {
    // queue empty
    while (!pq.empty())
        pq.pop();
    while (!tmp_pq.empty())
        tmp_pq.pop();
 
    // 변수
    scanf("%d %d %d"&height, &width, &total_time);
 
    // memset
    memset(flag, 0sizeof(flag));
 
    // scanf 배열 입력
    int tmp;
    for (int i = cen_y; i < cen_y + height; i++
        for (int j = cen_x; j < cen_x + width; j++) {
            scanf("%d"&tmp);
 
            // 줄기세포가 있을 경우, flag 처리
            if (tmp > 0) {
                flag[i][j] = tmp;
                
                // 줄기세포에 관한 정보를 우선순위 큐에 대입
                pq.push(make_pair(make_pair(i, j), make_pair(0, tmp)));
            }
        }
    
}
cs

드디어 풀었다..ㅠㅠ

역시 아무리 봐도 자료구조 자체에서는 문제가 없었다.
다만, 내가 우선순위 큐 안에 원소들을 좀 많이 넣다보니, 그 수의 몇제곱만큼의 연산량이 늘어버려서 
시간이 미세한 차이로 초과했던 것 같다.

이것도 거의 2일 잡아먹었다.
우선순위 큐를 활용해야 하는 문제 두 문제에서 고배를 마셨다
해당 유형을 잘 파헤쳐봐야겠다
더불어서, 시간 복잡도에 대한 염두도 꼭 하면서 코딩해야겠다



# 시간 복잡도 줄이기 위한 연산 

1. 우선순위 큐의 비교 연산자를 하나 빼줬다 - cmp 함수

2. 두 개의 우선순위 큐를 갖고 있었는데, 우선순위 큐 중에서 하나를 아예 빼줬다 (일반 큐로 전환)
- 우선순위 큐의 경우, 원소를 넣자마자 순서 배치를 하기 때문에, 
  자연스럽게 시간복잡도가 NlogN 으로 계산된다.
- 따라서, 굳이 "우선순위" 큐가 필요하지 않는 이상, 일반 큐를 사용해주자

3. 가장 중요했던 것, 큐에 원서를 집어넣을때도 선별해서 집어넣자(꼭)
   안그러면 몇 제곱 배의 연산량만큼 늘어나기 때문에, 치명적이다


'삼성 코팅테스트 준비 > 모의 역량 테스트 문제' 카테고리의 다른 글

1949 등산로 조성  (0) 2020.03.07
2382 미생물 격리  (0) 2020.03.06
2117 홈 방범 서비스  (0) 2020.03.05
4014 활주로 건설  (0) 2020.03.04
1953 탈주범 검거  (0) 2020.03.04