Algorithm/백준

[BOJ] - 16236. 아기 상어

benguin 2019. 7. 10. 12:43

[URL]

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

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가지고 있고, 이 크기는 자연수이다. 가장 처음에 아기 상어의 크기는 2이고, 아기 상어는 1초에 상하좌우로 인접한 한 칸씩 이동한다. 아기 상어는 자신의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없고, 나머지 칸은 모두 지나갈 수 있다. 아기 상어는 자신의 크

www.acmicpc.net

 

[풀이 과정]

* BFS + 시뮬

 

1. 아기 상어가 먹을 수 있는 물고기 개수를 구한다.

   먹을 수 있는 물고기 개수 = 0   -> 종료

   먹을 수 있는 물고기 개수 = 1   -> 그 위치(nearX, nearY)로 먹으러 간다

   먹을 수 있는 물고기 개수 > 1   -> 가장 가까운 물고기 구한다.  ->  그 위치(nearX, nearY)로 먹으러 간다

 

2. findNearFish()

  현재 (baby.x, baby.y) 위치로 부터 이동 가능 하며, 조건 (거리 같을때 가장 위쪽, 같으면 가장 왼쪽)을 가지고

  BFS탐색으로 가장 가까운 곳을 구한다. --> (nearX, nearY)

 

3. go()

목표 위치로 이동, map[][] 업데이트, 아기상어 현재 위치(baby.x, baby.y)  갱신, 아기상어 사이즈 갱신

 

 

 

[소스 코드]

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
 
struct BabyShark {
    int x;
    int y;
    int size;
    int sizeCheck;        // 변하는 상어사이즈 관리
};
BabyShark baby;
 
struct Fish {
    int x;
    int y;
    int dist;
};
 
int N;
int map[21][21];
int nearX = 0, nearY = 0, nearDist = 0;
 
int dx[] = { 00-11 };
int dy[] = { -1100 };
int resCnt = 0;
 
// 물고기 정렬 (같은 거리면 가장 위쪽, 가장 위쪽에서도 여러마리면 가장 왼쪽)
bool cmp(const Fish &a, const Fish &b) {
    if (a.x == b.x)
        return a.y < b.y;
    else
        return a.x < b.x;
}
 
// 초기화 & 입력
void init() {
    scanf("%d"&N);
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            scanf("%d"&map[i][j]);
            if (map[i][j] == 9)
            {
                baby.x = i;
                baby.y = j;
                baby.size = 2;
                baby.sizeCheck = 2;
                map[i][j] = 0;
            }
        }
    }
}
 
// 먹을 수 있는 물고기 갯수 구하기(수정 필요)
int findFish()
{
    int fishCnt = 0;
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (map[i][j] != 0 && map[i][j] < baby.size)
            {
                fishCnt++;
                nearX = i;
                nearY = j;
            }
        }
    }
 
    return fishCnt;
}
 
// 현재 아기상어 위치로 부터 destX, destY까지 이동할 수 있는 거리
int BFS(int destX, int destY) {
 
    queue <pair<intint>> q;
    bool visited[21][21= { 0, };
    int dist[21][21= { 0, };
 
 
    visited[baby.x][baby.y] = true;
    dist[baby.x][baby.y] = 0;
    q.push(make_pair(baby.x, baby.y));
 
    while (!q.empty())
    {
        int cx = q.front().first;
        int cy = q.front().second;
        q.pop();
 
        for (int k = 0; k < 4; k++)
        {
            int nx = cx + dx[k];
            int ny = cy + dy[k];
 
            if (nx >= 0 && ny >= 0 && nx < N && ny < N)
            {
                if (map[nx][ny] <= baby.size && visited[nx][ny] == false)
                {
                    visited[nx][ny] = true;
                    dist[nx][ny] = dist[cx][cy] + 1;
                    q.push(make_pair(nx, ny));
                }
            }
        }
    }
 
    return dist[destX][destY];
}
 
 
// 가장 가까운 물고기 찾자 
void findNearFish() {
    vector <Fish> v;
 
    int Min = 987654;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (map[i][j] != 0 && map[i][j] < baby.size)
            {
                int tempDist = BFS(i, j);
 
                if (Min >= tempDist && tempDist > 0)
                {
                    Min = tempDist;
                }
            }
        }
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (map[i][j] != 0 && map[i][j] < baby.size)
            {
                if (BFS(i, j) == Min)
                {
                    Fish temp;
                    temp.x = i;
                    temp.y = j;
                    temp.dist = Min;
 
                    v.push_back(temp);
                }
            }
        }
    }
 
    if (v.size() != 0)
    {
        sort(v.begin(), v.end(), cmp);
 
        nearX = v.front().x;
        nearY = v.front().y;
        nearDist = v.front().dist;
    }
    else
    {
        nearDist = 0;
    }
 
    v.clear();
}
 
void go(int destX, int destY, int nearDist)        // 목적지 x, y로 이동하여 물고기 먹음!
{
    resCnt += nearDist;
 
    baby.x = destX;
    baby.y = destY;
 
    map[destX][destY] = 0;
 
    baby.sizeCheck--;
    if (baby.sizeCheck == 0)
    {
        baby.size++;
        baby.sizeCheck = baby.size;
    }
}
 
int main() {
    init();
 
    while (true)
    {
        int fishCnt = findFish();
 
        // 1.없는 경우
        if (fishCnt == 0)
            break;
 
        // 2.한 마리인 경우
        if (fishCnt == 1)
        {
            nearDist = BFS(nearX, nearY);
            if (nearDist == 0)
                break;
            else
                go(nearX, nearY, nearDist);            // 먹으로 출발
        }
 
        // 3.여러 마리인 경우
        if (fishCnt > 1)
        {
            findNearFish();            // 찾자 가장 가까운 물고기
 
            if (nearDist == 0)
                break;
            else
                go(nearX, nearY, nearDist);            // 먹으로 출발
        }
    }
 
    printf("%d\n", resCnt);
 
    return 0;
}
cs

'Algorithm > 백준' 카테고리의 다른 글

[BOJ] - 17143. 낚시왕  (0) 2019.07.31
17140. - 이차원 배열과 연산  (0) 2019.07.16
[BOJ] - 13023. ABCDE  (0) 2019.07.10
[BOJ] - 14502. 연구소  (0) 2019.07.03
[BOJ] - 2156. 포도주 시식  (0) 2019.07.01