jiho_bae
Go devlog
jiho_bae
전체 방문자
오늘
어제
  • 분류 전체보기 (158)
    • JavaScript (38)
      • theory (34)
      • vanilla (4)
    • HTML & CSS (2)
    • Browser (3)
    • CS (6)
      • linux (1)
      • shell (2)
      • compiler (2)
    • DS & Algorithm (87)
      • theory (5)
      • basic (7)
      • programmers (30)
      • baekjoon (45)
    • Design Pattern (2)
    • Error (4)
    • Git & Github (4)
    • Tools (1)
    • 부트캠프 (4)
    • Small Tips (2)
    • Java (3)
    • test (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 계수정렬 자바스크립트
  • 자바스크립트 모듈 시스템
  • 외벽 점검 javascript
  • 자바스크립트 이벤트 위임
  • JavaScript
  • 1753 최단경로 javascript
  • 덧칠하기 javascript
  • 자바스크립트 커링
  • 자바스크립트 비동기 마이크로 태스크 큐와 렌더링 과정
  • 자바스크립트 sort는 왜 그모양일까
  • 리액트 프로젝트 디버깅하기
  • 깃 이전 커밋에서 새 브랜치 만들기
  • 억억단을 외우자 javascript
  • safari Date format NaN
  • safari invalid date error
  • 퀵정렬 자바스크립트
  • 백준 17406 nodeJS
  • 백준 자바스크립트 입력 템플릿
  • 병합정렬 자바스크립트
  • 13460 javascript nodejs
  • 프로그래머스 숫자카드나누기 javascript
  • 리코쳇 로봇 javascript
  • 가사 검색 자바스크립트
  • 25632 소수 부르기 게임
  • fetch 취소하기
  • 자바스크립트 채팅방 스크롤
  • 자바스크립트 배열의 특수함
  • javascript use strict
  • 카카오 코딩테스트 양궁대회 nodeJS
  • 대충만든자판 javascript

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
jiho_bae

Go devlog

DS & Algorithm/baekjoon

[백준] 16197번 두 동전 - JavaScript(NodeJS)

2021. 6. 7. 16:45

문제

 

16197번: 두 동전

N×M 크기의 보드와 4개의 버튼으로 이루어진 게임이 있다. 보드는 1×1크기의 정사각형 칸으로 나누어져 있고, 각각의 칸은 비어있거나, 벽이다. 두 개의 빈 칸에는 동전이 하나씩 놓여져 있고,

www.acmicpc.net

 

풀이

문제의 조건을 요약해보자.

 

동전이 2개 주어진다.
버튼을 클릭해서 동전을 상하좌우로 이동시킨다.
동전은 벽을 넘을 수 없고, 보드에서 떨어뜨릴 수 있다.
두 동전은 같은 방향으로 한 칸씩 이동한다.

 

이를 참고해 두 동전 중 하나만을 떨어뜨리기 위해 버튼을 최소 몇번 눌러야 할지 구하자.

 

풀이 방향

우선 동전의 위치를 구해야 한다.

별 다른 방법이 없으므로, 보드 행렬에서 한칸씩 모두 조회해야 한다.

 

2개의 동전의 위치를 모두 구했다면, 버튼을 눌러 동전을 이동시킨다.

버튼은 최대 10번 누를 수 있다.

 

경우의 수는 상하좌우로 총 4번, 4의 10승 = 최대 약 100만번으로 조회해보기에 충분하다.

DFS를 통해 모든 경우의 수를 조회해본다.

 

재귀를 탈출하기 위한 조건을 설정한다.

 

1. 버튼을 10번 초과시켜서 눌렀다면 탈출
2. 두 동전이 모두 떨어지면 탈출
3. 두 동전중 한 동전이 떨어졌다면, 최솟값 여부를 판별하고 탈출

 

그리고 상하좌우 이동을 판별할 때, 벽이 있다면 이동할 수 없음을 반영한다.(벽에 걸리는 코인은 이동시키지 않으면 된다.)

 

최솟값 판단은 오로지 한개의 동전만 떨어졌을 때 실행되므로
dfs 재귀가 모두 끝나고 정답을 출력하기 전에

최솟값이 갱신되지 않았다면 10회 안에 하나의 동전만을 떨어뜨리는게 불가능하므로, -1을 출력한다.

갱신되었다면 최솟값을 출력하면 되겠다.

 

이제 코드를 보자.

 

코드

const sol = (input) => {
  const [N, M] = input[0].split(" ").map(Number);
  const board = input.slice(1).map((str) => str.split(""));
  const coin = [];
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < M; j++) {
      if (board[i][j] === "o") coin.push([i, j]);
    }
  }

  const dx = [-1, 0, 1, 0];
  const dy = [0, 1, 0, -1];
  let min = Number.MAX_SAFE_INTEGER;

  function checkDrop(x, y) { // 떨어지면 참, 떨어지지 않았으면 거짓
    if (x < 0 || y < 0 || x >= N || y >= M) return true;
    return false;
  }

  function checkWall(x, y, idx) {
    const [nx, ny] = [x + dx[idx], y + dy[idx]];
    if (board[nx]) { 
      if (board[nx][ny] === "#") return [x, y];
    }
    return [nx, ny];
  } // 중요한 부분. 먼저 행이 존재하는지를 검사한다.(board[-1][2]는 undefined의 2번 인덱스를 참조하려 하기 때문에 에러가 발생한다.)

  function dfs(cnt, x1, y1, x2, y2) {
    if (cnt >= min) return; // 없어도 정답은 나온다. 하지만 10이하의 min값이 나왔다면 더 빠르게 돌아간다. 
    if (cnt > 10) return;
    if (checkDrop(x1, y1) && checkDrop(x2, y2)) return;
    if (checkDrop(x1, y1) || checkDrop(x2, y2)) { // 둘 중 하나만 참일 때만이 최솟값을 갱신할 수 있다.
      min = Math.min(min, cnt);
      return;
    }
    for (let i = 0; i < 4; i++) {
      const [nx1, ny1] = checkWall(x1, y1, i); // 벽이 있으면 (x,y), 벽이 없다면 이동 가능하므로 (nx,ny)
      const [nx2, ny2] = checkWall(x2, y2, i); // 단, (nx,ny)가 보드 바깥일 수도 있지만, 다음 재귀에서 판별할 것이기 때문에 상관x
      dfs(cnt + 1, nx1, ny1, nx2, ny2);
    }
  }

  dfs(0, coin[0][0], coin[0][1], coin[1][0], coin[1][1]);
  if (min === Number.MAX_SAFE_INTEGER) return -1; // 최솟값이 갱신되지 않았다면!
  return min;
};

// 백준에서 입력을 받는 코드
const input = [];
require("readline")
  .createInterface(process.stdin, process.stdout)
  .on("line", (line) => {
    input.push(line);
  })
  .on("close", () => {
    console.log(sol(input));
    process.exit();
  });
저작자표시 (새창열림)

'DS & Algorithm > baekjoon' 카테고리의 다른 글

[백준] 9663번 N-Queen - JavaScript(NodeJS)  (1) 2021.06.08
[백준] 16198번 에너지 모으기 - JavaScript(NodeJS)  (0) 2021.06.08
[백준] 15658번 연산자 끼워넣기(2) - JavaScript(NodeJS)  (0) 2021.06.07
[백준] 14225번 부분수열의 합 - JavaScript(NodeJS)  (0) 2021.06.05
[백준] 1182번 부분수열의 합 - JavaScript(NodeJS)  (0) 2021.06.05
    'DS & Algorithm/baekjoon' 카테고리의 다른 글
    • [백준] 9663번 N-Queen - JavaScript(NodeJS)
    • [백준] 16198번 에너지 모으기 - JavaScript(NodeJS)
    • [백준] 15658번 연산자 끼워넣기(2) - JavaScript(NodeJS)
    • [백준] 14225번 부분수열의 합 - JavaScript(NodeJS)
    jiho_bae
    jiho_bae
    하루에 한 걸음씩

    티스토리툴바