알고리즘/BOJ 문제풀이

[BFS]BOJ 16236_아기 상어

4Legs 2020. 10. 11. 02:50

문제 링크 : www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��

www.acmicpc.net

 

삼성 SW 역량 테스트 기출문제이다.

이 문제도 전형적인 2차원 배열에서의 BFS 문제이지만, 단순 BFS로는 해결되지 않는 부분이 있다.

 

문제의 조건에서,

먹을 수 있는 물고기가 1마리보다 많다면, 거리가 가장 가까운 물고기를 먹으러 간다.

  • 거리는 아기 상어가 있는 칸에서 물고기가 있는 칸으로 이동할 때, 지나야하는 칸의 개수의 최솟값이다.
  • 거리가 가까운 물고기가 많다면, 가장 위에 있는 물고기, 그러한 물고기가 여러마리라면, 가장 왼쪽에 있는 물고기를 먹는다.

라고 제시되었기 때문에

BFS를 실행할 때 큐에 삽입되는 물고기들의 좌표들의 조정이 필요하다.

 

가령, 이 경우를 보자.

각 칸에 적힌 숫자는 북-동-남-서 순서로 탐색할 때 각 칸이 탐색되는 순서이다.

이 경우에서 11번 칸의 물고기가 13번 칸의 물고기보다 먼저 탐색되는데,

문제의 조건에서 13번에 있는 물고기가 먼저 먹혀야 한다.

따라서, 물고기들을 큐에 넣을 때 row, col 이 작은 순으로 정렬해서 넣어야 한다.

이 과정에서, 우선순위 큐(Priority Queue)가 사용된다.

 

물고기들을 좌표를 기준으로 정렬해서 큐에 넣었을 때, 이런 경우도 보자.

이 경우 (1, 1)의 물고기가 (1, 3)에 있는 물고기보다 거리가 더 멀지만,

좌표 정렬에 의해 (1, 1)의 물고기에게 먼저 먹히게 된다.

따라서, 우선순위 큐의 정렬 기준에 물고기의 거리도 포함시켜야 한다.

즉, 거리 - 행 - 열 순으로 정렬되도록 우선순위 큐를 사용해야 한다.

 

[코드]

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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <memory.h>
 
using namespace std;
typedef pair<intint> p;
 
int n, range_r, range_c;
int board[21][21], visit[21][21], fishes[9];
int live_time, eat_cnt, level = 2;
p dir[4= { {-10}, {0-1}, {10}, {01} }; //0123-NWSE
priority_queue<pair<int, p>vector<pair<int, p>>, greater<pair<int, p>>> que;
pair<intint> cur_pos;
 
pair<intint> bfs() {
    que.push({ 0, cur_pos });
 
    while (!que.empty()) {
        pair<intint> cur = que.top().second;
        que.pop();
 
        //현재 먹을 수 있는 물고기라면 함수 종료
        int v = board[cur.first][cur.second];
        if (v > 0 && v < level) {
            eat_cnt++;
            board[cur.first][cur.second] = 0;
            live_time += visit[cur.first][cur.second];
            return cur;
        }
 
        for (int i = 0; i < 4; i++) {
            int newR = cur.first + dir[i].first;
            int newC = cur.second + dir[i].second;
            if (newR < 1 || newR > n || newC < 1 || newC > n) continue;
            if (visit[newR][newC] > 0 || board[newR][newC] > level) continue;
 
            visit[newR][newC] = visit[cur.first][cur.second] + 1;
            que.push({ visit[newR][newC], { newR, newC } });
        }
    }
    return { -1-1 };
}
 
void init() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            int val;
            cin >> val;
            if (val == 9) cur_pos = { i, j };
            else {
                board[i][j] = val;
                fishes[val]++;
            }
        }
}
 
int main() {
    init();
 
    while (1) {
        memset(visit, 0sizeof(visit));
        pair<intint> result = bfs();
        if (result.first == -1break;
        if (eat_cnt == level) { level++; eat_cnt = 0; }
        cur_pos = result;
        while (!que.empty()) que.pop();
    }

    printf("%d\n", live_time);
    return 0;
}
 
cs

 

'알고리즘 > BOJ 문제풀이' 카테고리의 다른 글

[DP] BOJ 1256_사전  (0) 2020.10.15
[Segtree]BOJ 2243_사탕 상자  (0) 2020.10.12
[BFS]BOJ 1194_달이 차오른다, 가자.  (0) 2020.10.08
[BFS]BOJ 1726_로봇  (0) 2020.10.06
[DFS]BOJ 16437_양 구출 작전  (0) 2020.10.03