Be a developer

백준 16236 아기상어 본문

sw 역량테스트

백준 16236 아기상어

중국고대사 2019. 4. 9. 23:13

코딩 테스트를 5일 앞두고 기출 문제를 조금씩 풀려고 한다.

푸는데 성공하면 글을 쓰겠지만, 못 풀면 이 문제 이후로 업데이트가 없을 수도..

 

알고리즘 2를 수강하면서 한 번 풀어보았던 문제여서 그래도 풀 수 있었던 것 같다.

한 번 이동이 가중치 1이고, 계속해서 가장 가까운 물고기를 찾아야 하기 때문에 bfs를 통해 풀 수 있다.

n의 크기가 최대 20이기 때문에 시간 복잡도도 충분하다.

 

무한 루프를 통해서 bfs를 계속 돌면서 먹을 수 있는 물고기를 찾는다.

만약 먹을 수 있는 물고기가 더이상 없으면 무한루프를 종료한다.

 

먹을 수 있는 물고기를 vector에 추가하고, 여러 마리가 있을 경우 row와 col을 비교하여 처리하는 것이 조금 귀찮은 문제인 것 같다.

 

물고기를 먹고 나면 dist 배열을 초기화 해주고, 그 위치에서 다시 시작하면 된다.

 

코드는 아래와 같다. 디버깅을 위한 출력문들도 주석처리 되어 있다.

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
140
141
142
143
144
145
146
147
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
using namespace std;
 
int map[20][20];
int dist[20][20];
 
int dr[4= { -1,0,1,0 };
int dc[4= { 0,1,0,-1 };
 
int main(int argc, char** argv) {
    int n, lv = 2, exp = 0, ans = 0;
    cin >> n;
    
    queue<pair<intint>> q;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d"&map[i][j]);
            //시작 위치를 push
            if (map[i][j] == 9) {
                q.push(make_pair(i, j));
                dist[i][j] = 1;
                map[i][j] = 0;
            }
        }
    }
    //printf("\n");
    //먹이를 한 번 찾을 때 마다 bfs를 돌아야 하니까 무한 루프를 돈다.
    while (1) {
        vector<tuple<intintint>> obj;
        while (!q.empty()) {
            int row = q.front().first;
            int col = q.front().second;
            q.pop();
 
            for (int i = 0; i < 4; i++) {
                int nr = row + dr[i];
                int nc = col + dc[i];
 
                if (nr < 0 || nr >= n || nc < 0 || nc >= n)continue;
                //lv이 더 높은 물고기가 있으면 못 지나간다.
                if (lv < map[nr][nc])continue;
                //이미 지나간 곳은 안가도 된다. 최소 거리를 찾아야 하기 때문에
                if (dist[nr][nc] != 0)continue;
                //잡아 먹을 수 있으면 먹이 리스트에 저장한다.
                if (lv > map[nr][nc] && map[nr][nc] != 0) {
                    dist[nr][nc] = dist[row][col] + 1;
                    q.push(make_pair(nr, nc));
                    //먹을 수 있는 list에 추가한다.
                    obj.push_back(make_tuple(nr, nc, dist[nr][nc]));
                }
                else {
                    dist[nr][nc] = dist[row][col] + 1;
                    q.push(make_pair(nr, nc));
                }
            }
            /* 출력부분
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    printf("%d ", dist[i][j]);
                }
                printf("\n");
            }
            printf("\n");
            */
        }
        /*출력부분
        printf("bfs종료\n");
        printf("먹을 수 있는 물고기: %d\n", obj.size());
        */
        //먹을 수 있는 물고기가 없으면 종료
        if (obj.size() == 0) {
            break;
        }
        int min_idx, min_dis = 100;
        //갈 수 있는 곳을 모두 다 돌았으면 먹을 걸 고른다.
        for (int i = 0; i < obj.size(); i++) {
            //공간의 크기가 최대 20이므로 최대값을 그냥 100으로 준다.
            int row, col, dis;
            tie(row, col, dis) = obj[i];
            //최소 거리를 찾아간다.
            if (min_dis > dis) {
                min_dis = dis;
                min_idx = i;
            }//거리가 같을 경우
            else if (min_dis == dis) {
                //가장 위에 있는 물고기를 선택
                int cmp_row, cmp_col, cmp_dis;
                tie(cmp_row, cmp_col, cmp_dis) = obj[min_idx];
                if (row < cmp_row) {
                    min_idx = i;
                }
                //같은 높이에 있을 경우
                if (row == cmp_row) {
                    //가장 왼쪽에 있는 물고기를 선택
                    if (col < cmp_col) {
                        min_idx = i;
                    }
                }
            }
        }
        //가장 가까이 있는 물고기의 위치
        int objr, objc, objd;
        tie(objr, objc, objd) = obj[min_idx];
        //경험치 올라가고, 그 공간은 0으로 만든다.
        exp++;
        //level up!!
        if (exp == lv) {
            exp = 0;
            lv++;
        }
        map[objr][objc] = 0;
        //이동한 시간을 더해준다.
        ans += dist[objr][objc] - 1;
        //dist를 초기화 해준다.
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                dist[i][j] = 0;
            }
        }
        //방금 물고기를 먹은 위치를 다시 시작위치로 넣어준다.
        q.push(make_pair(objr, objc));
        dist[objr][objc] = 1;
 
        /*출력부분
        //lv, exp 출력
        printf("lv: %d, exp: %d\n", lv, exp);
        printf("현재 걸린 시간: %d\n", ans);
        //바뀐 맵 출력
        printf("--------------바뀐 맵----------------\n");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                printf("%d ", map[i][j]);
            }
            printf("\n");
        }
        printf("-----------------------------\n");
        */
    }
 
    printf("%d\n", ans);
 
 
    return 0;
}
cs

'sw 역량테스트' 카테고리의 다른 글

백준 15684 사다리 조작  (0) 2019.04.12
백준 15685 드래곤 커브  (0) 2019.04.11
백준 15686 치킨 배달  (0) 2019.04.11
백준 16234 인구 이동  (0) 2019.04.10
백준 16235 나무 재테크  (0) 2019.04.10
Comments