본문 바로가기

알고리즘/백준

[백준] 16236번 아기 상어

반응형

16236번 아기 상어


1. 이해하기

  • 가장 처음에 아기 상어의 크기는 2이고, 1초에 상하좌우로 인접한 한 칸씩 이동할 수 있다.
  • 아기 상어는 자산의 크기보다 큰 물고기가 있는 칸은 지나갈 수 없다.
  • 아기 상어는 자신의 크기보다 작은 물고기만 먹을 수 있다. 크기가 같은 물고기는 먹을 수 없지만 지나갈 수는 있다.
  • 아기 상어가 어디로 이동할지 결정하는 방법
    • 더 이상 먹을 수 있는 물고기가 없을 때 아기 상어는 엄마 상어에게 도움을 요청한다.
    • 먹을 수 있는 물고기가 1마리라면, 그 물고기를 먹으러 간다.
    • 먹을 수 있는 물고기가 1마리보다 많다면, 거리가 가장 가까운 물고기를 먹으러 간다.
      • 거리는 아기 상어가 있는 칸에서 물고기가 있는 칸으로 이동할 때, 지나야 하는 칸의 개수의 최솟값이다.
      • 거리가 가까운 물고기가 많다면, 가장 위, 그러한 물고기가 여러마리라면, 가장 왼쪽에 있는 물고기를 먹는다.
  • 아기 상어가 물고기를 먹는데 걸리는 시간은 없다. 먹으면 그 칸은 빈칸이 된다.
  • 아기 상어는 자신의 크기와 같은 수의 물고기를 먹을 때마다 크기가 1 증가한다.
  • 아기 상어가 엄마 상어의 도움을 바랄 때의 시간을 구하는 문제.

2. 구현하기

  • 물고기가 각 물고기를 먹으러 가는데 걸리는 거리를 bfs를 이용하여 구한다.

    void bfs(Shark shark) {
        memset(dist,-1,sizeof(dist));
        queue<Point> q;
        q.push({shark.p.x,shark.p.y});
        dist[shark.p.x][shark.p.y] = 0;
        while(!q.empty()) {
            int x = q.front().x, y = q.front().y; q.pop();
            for(int i = 0; i < 4; i++) {
                int nx = x+dx[i], ny = y+dy[i];
                if(nx < 0 or nx >= N or ny < 0 or ny >= N) continue;
                if(dist[nx][ny] != -1) continue;
                if(map[nx][ny] > shark.size) continue;
                q.push({nx,ny});
                dist[nx][ny] = dist[x][y]+1;
            }
        }
    }
  • 거리를 구한 것을 바탕으로 아기 상어가 위치할 다음 좌표를 구한다.

    Point get_next_location(Shark shark) {
        bfs(shark);
        Point next = {-1,-1};
        int min_dist = -1;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < N; j++) {
                if(1 <= map[i][j] and map[i][j] <= 6 and dist[i][j] != -1) {
                    if(shark.size <= map[i][j]) continue;
                    if(min_dist == -1 || dist[i][j] < min_dist)  {
                        next = {i,j}; min_dist = dist[i][j];
                    }
                }
            }
        }
        return next;
    }
  • 먹을 물고기가 없을 때까지 반복한다.

    int simulate(Shark shark) {
        int time = 0;
        while(1) {
            Point next = get_next_location(shark);
            if(next.x == -1) break;
            time += dist[next.x][next.y];
            map[next.x][next.y] = 0;
            shark.p = next; shark.cnt++;
            if(shark.cnt == shark.size) {
                shark.cnt = 0; shark.size++;
            }
        }
        return time;
    }

3. 전체 코드

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
struct Point {
    int x,y;
};
struct Shark {
    Point p;
    int size,cnt;
};
int map[20][20];
int dist[20][20];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int N;

void bfs(Shark shark) {
    memset(dist,-1,sizeof(dist));
    queue<Point> q;
    q.push({shark.p.x,shark.p.y});
    dist[shark.p.x][shark.p.y] = 0;
    while(!q.empty()) {
        int x = q.front().x, y = q.front().y; q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x+dx[i], ny = y+dy[i];
            if(nx < 0 or nx >= N or ny < 0 or ny >= N) continue;
            if(dist[nx][ny] != -1) continue;
            if(map[nx][ny] > shark.size) continue;
            q.push({nx,ny});
            dist[nx][ny] = dist[x][y]+1;
        }
    }
}

Point get_next_location(Shark shark) {
    bfs(shark);
    Point next = {-1,-1};
    int min_dist = -1;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            if(1 <= map[i][j] and map[i][j] <= 6 and dist[i][j] != -1) {
                if(shark.size <= map[i][j]) continue;
                if(min_dist == -1 || dist[i][j] < min_dist)  {
                    next = {i,j}; min_dist = dist[i][j];
                }
            }
        }
    }
    return next;
}

int simulate(Shark shark) {
    int time = 0;
    while(1) {
        Point next = get_next_location(shark);
        if(next.x == -1) break;
        time += dist[next.x][next.y];
        map[next.x][next.y] = 0;
        shark.p = next; shark.cnt++;
        if(shark.cnt == shark.size) {
            shark.cnt = 0; shark.size++;
        }
    }
    return time;
}

void input(Shark& shark) {
    cin >> N;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            cin >> map[i][j];
            if(map[i][j] == 9) {
                shark = {{i,j},2,0};
                map[i][j] = 0;
            }
        }
    }
}

int main() {
    Shark shark;
    input(shark);
    cout << simulate(shark) << '\n';
    return 0;
}

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

[백준] 17143번 낚시왕  (0) 2019.10.11
[백준] 17144번 미세먼지 안녕!  (0) 2019.10.11
[백준] 16235번 나무 재테크  (0) 2019.10.10
[백준] 16234번 인구 이동  (0) 2019.10.09
[백준] 5373번 큐빙  (0) 2019.10.08