[JS][백준]16236_아기 상어
Algorithm/BaeKJoon

[JS][백준]16236_아기 상어

문제 번호

 

16236번: 아기 상어

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

www.acmicpc.net

 

 

알고리즘 분류

 

문제 풀이

 상어 시리즈 문제이다.

BFS에 약간의 구현을 곁들이면 쉽게 풀 수 있다.

 

 우리의 아기 상어는 자신보다 작은 물고기를 먹을 수 있고, 더 큰 물고기는 통과하지 못한다.

문제에서 주어진 먹을 수 있는 물고기의 조건을 확인하여 BFS로 먹을 수 있는 물고기를 찾아보자.

우선적으로 가장 가까운 위치의 물고기를 목표로 하기 때문에 BFS에서 최단거리에 있는 물고기를 발견한다면 더 탐색할 필요는 없다.

 같은거리에 있는 물고기가 여러 마리일 수 있으므로 food라는 배열에 넣어서 return 해줄 것이다.

function BFS(N, map, shark) {
  let food = [];
  let visited = new Array(N).fill(null).map(_ => new Array(N).fill(false));
         // 상 우 하 좌
  let dx = [0, 1, 0, -1];
  let dy = [-1, 0, 1, 0];

  let q = new Queue();
  q.push(shark.x, shark.y, 0);

  let min = Infinity;
  while (q.length()) {
    let cur = q.pop();
    let [curX, curY, curDist] = [cur.x, cur.y, cur.dist]; // 위치와 거리
    if (map[curY][curX] !== 0 && map[curY][curX] < shark.size) {  // 먹을 수 있는 물고기라면.
      if (curDist < min) // 최단거리에 있는 물고기 까지의 최단거리 찾기.
        min = curDist;
      if (curDist <= min) {  // 먹을 수 있는 물고기 후보군 추가.
        food.push({
          x: curX,
          y: curY,
          dist: curDist
        })
      }
    }

    for (let next = 0; next < 4; next++) {
      let [nextX, nextY] = [curX + dx[next], curY + dy[next]];
      if (nextX < 0 || nextX >= N || nextY < 0 || nextY >= N) continue;
      if (!visited[nextY][nextX] && map[nextY][nextX] <= shark.size && curDist < min) {
        visited[nextY][nextX] = true;
        q.push(nextX, nextY, curDist + 1);
      }
    }
  }
  return food;
}
main();

 

 BFS를 통해서 먹을 수 있는 물고기들의 위치를 받아왔으면 문제에서 주어진 조건을 잘 살펴봐서 어떤 물고기를 먹어야 하는지 알아보자.

    let food = BFS(N, map, shark);
    food.sort((a, b) => {      
        if (a.y < b.y) return -1;
        else if (a.y > b.y) return 1;
        else {
          if (a.x < b.x) return -1;
          else if (a.x > b.x) return 1;
          return 0;
        }
      }
  )

 

먹을 물고기를 찾았으면 먹으면 된다.

상어는 자신의 몸집과 같은 수만큼의 물고기를 먹으면 몸집이 한 단계 커진다. 그래서 상어가 커지기 위해서 더 먹어야 하는 물고기의 수를 shark.exp라고 설정했다.

// 3. 먹자.
    if (food.length === 0) // 먹을게 없는경우. 
      return time;
    time += food[0].dist;
    shark.exp--;
    if (shark.exp === 0) {
      shark.size++;
      shark.exp = shark.size;
    }
    [shark.x, shark.y] = [food[0].x, food[0].y];
    map[food[0].y][food[0].x] = 0;

 

전체 코드

class Node {
  constructor(x, y, dist) {
    this.x = x;
    this.y = y;
    this.dist = dist;
    this.next = null;
  }
}
class Queue {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }
  length() {
    return this.size;
  }
  push(x, y, dist) {
    let node = new Node(x, y, dist);
    if (this.size === 0) {
      this.head = node;
      this.tail = node;
    } else {
      this.tail.next = node;
      this.tail = node;
    }
    this.size++;
  }
  pop() {
    let temp = this.head;
    if (this.size <= 1) {
      this.head = null;
      this.tail = null;
    } else {
      this.head = this.head.next;
    }
    this.size--;
    return temp;
  }
}
function main() {
  const input = require('fs').readFileSync('dev/stdin').toString().trim().split('\n');
  const N = +input[0];
  let map = input.slice(1).map(_ => _.trim().split(' ').map(Number));

  // shark init.
  let shark = {
    x: 0,
    y: 0,
    size: 2,
    exp: 2
  }
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      if (map[i][j] === 9) {
        [shark.x, shark.y] = [j, i];
        map[i][j] = 0;
      }
    }
  }

  console.log(sol(N, map, shark));
}
function sol(N, map, shark) {
  /**
 * 맵 최대 400.
 * 먹을 수 있는 물고기가 몇마린지?  최대 399마리.
 * 1. 먹을 수 있는 물고기가 몇마리인지.
 * 2. 여러 마리라면 그 물고기들 까지의 거리를 구한다.(BFS)
 *    2-1 거리가 같다면 문제의 조건을 따른다.
 * 3. 상어의 크기가 변경될때 마다 1번을 다시 구해야한다.
 * 4. 1번에서 더 이상 먹을 수 있는 물고기가 없다고 판명되면 종료한다.
 */
  let time = 0;
  while (1) { 
    // 2.가장 가까운 물고기들.
    let food = BFS(N, map, shark);
    food.sort((a, b) => {      
        if (a.y < b.y) return -1;
        else if (a.y > b.y) return 1;
        else {
          if (a.x < b.x) return -1;
          else if (a.x > b.x) return 1;
          return 0;
        }
      }
  )

    // 3. 먹자.
    if (food.length === 0) // 먹을게 없는경우. 
      return time;
    time += food[0].dist;
    shark.exp--;
    if (shark.exp === 0) {
      shark.size++;
      shark.exp = shark.size;
    }
    [shark.x, shark.y] = [food[0].x, food[0].y];
    map[food[0].y][food[0].x] = 0;
  }

}
function BFS(N, map, shark) {
  let food = [];
  let visited = new Array(N).fill(null).map(_ => new Array(N).fill(false));
         // 상 우 하 좌
  let dx = [0, 1, 0, -1];
  let dy = [-1, 0, 1, 0];

  let q = new Queue();
  q.push(shark.x, shark.y, 0);

  let min = Infinity;
  while (q.length()) {
    let cur = q.pop();
    let [curX, curY, curDist] = [cur.x, cur.y, cur.dist]; // 위치와 거리
    if (map[curY][curX] !== 0 && map[curY][curX] < shark.size) {  // 먹을 수 있는 물고기라면.
      if (curDist < min) // 최단거리에 있는 물고기 까지의 최단거리 찾기.
        min = curDist;
      if (curDist <= min) {  // 먹을 수 있는 물고기 후보군 추가.
        food.push({
          x: curX,
          y: curY,
          dist: curDist
        })
      }
    }

    for (let next = 0; next < 4; next++) {
      let [nextX, nextY] = [curX + dx[next], curY + dy[next]];
      if (nextX < 0 || nextX >= N || nextY < 0 || nextY >= N) continue;
      if (!visited[nextY][nextX] && map[nextY][nextX] <= shark.size && curDist < min) {
        visited[nextY][nextX] = true;
        q.push(nextX, nextY, curDist + 1);
      }
    }
  }
  return food;
}
main();

 

특이사항

 문제를 빠르게 풀진 못한 것 같지만 헤매면서 풀지는 않았다. 길이가 긴 구현 문제라면 천천히 풀더라도 코드를 다시 작성하는 일이 없도록 정확하게 푸는 게 더 중요한 것 같다.

 

'Algorithm > BaeKJoon' 카테고리의 다른 글

[JS][백준]1107_리모컨  (0) 2022.09.20
[JS][백준]1238_파티  (0) 2022.09.20
[JS][백준]2252_줄 세우기  (0) 2022.09.15
[JS][백준]1197_최소 스패닝 트리  (0) 2022.09.14
[JS][백준]1052_물병  (0) 2022.09.04