백준 4179 불!

2025. 1. 17. 15:55·코딩테스트/bfs (Breadth-first search)

링크 : https://www.acmicpc.net/problem/4179

문제 설명

더보기

문제

지훈이는 미로에서 일을 한다. 지훈이를 미로에서 탈출하도록 도와주자!

미로에서의 지훈이의 위치와 불이 붙은 위치를 감안해서 지훈이가 불에 타기전에 탈출할 수 있는지의 여부, 그리고 얼마나 빨리 탈출할 수 있는지를 결정해야한다.

지훈이와 불은 매 분마다 한칸씩 수평또는 수직으로(비스듬하게 이동하지 않는다) 이동한다.

불은 각 지점에서 네 방향으로 확산된다.

지훈이는 미로의 가장자리에 접한 공간에서 탈출할 수 있다.

지훈이와 불은 벽이 있는 공간은 통과하지 못한다.

입력

입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다.

다음 입력으로 R줄동안 각각의 미로 행이 주어진다.

각각의 문자들은 다음을 뜻한다.

  • #: 벽
  • .: 지나갈 수 있는 공간
  • J: 지훈이의 미로에서의 초기위치 (지나갈 수 있는 공간)
  • F: 불이 난 공간

J는 입력에서 하나만 주어진다.

출력

지훈이가 불이 도달하기 전에 미로를 탈출 할 수 없는 경우 IMPOSSIBLE 을 출력한다.

지훈이가 미로를 탈출할 수 있는 경우에는 가장 빠른 탈출시간을 출력한다.


문제 풀이

  • 1. input 처리
    • jIndex : 지훈의 좌표
    • fireIndex : 불의 좌표
  • 2. bfs 로직 구현
    • 지훈의 좌표를 통해 지훈이 갈 수 있는 위치를 jIndex에 추가 및 arr 초기화
      •   지훈의 좌표가 arr상에 'J'가 아닐 경우(불에의해 'F'로 될 수 있음) 검사 안함
      •   이 때, 탈출을 할 수 있는 좌표면 answer를 count + 1로 초기화
    • answer가 0이 아니면 break -> 탈출한 것이므로 더이상 검사할 필요가 없음
    • 불의 좌표를 통해 불이 갈 수 있는 위치를 fireIndex에 추가 및 arr 초기화
  • 3. 최종 결과
    • answer가 0이면 'IMPOSSIBLE' 리턴, 아니면 answer 값 리턴
const inputs = require("fs")
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");

const [r, c] = inputs[0].split(" ").map(Number);
let arr = [];

let jIndex = [];
let fireIndex = [];
for (let i = 1; i <= r; i++) {
  const input = inputs[i].split("");
  arr.push(input);
  input.forEach((value, xIndex) => {
    if (value === "J") jIndex.push([i - 1, xIndex, 0]);
    else if (value === "F") fireIndex.push([i - 1, xIndex]);
  });
}

let move = [
  [-1, 0],
  [1, 0],
  [0, 1],
  [0, -1],
];

let answer = 0;
const bfs = () => {
  while (jIndex.length > 0) {
    // 지훈의 이동
    let jLen = jIndex.length;
    for (let i = 0; i < jLen; i++) {
      let [jy, jx, count] = jIndex.shift();
      // 지훈이 살아있다면 (불에 타죽었으면 해당 값은 'F'로 변함)
      if (arr[jy][jx] !== "J") continue;

      move.forEach((j) => {
        let my = jy + j[0];
        let mx = jx + j[1];
        if (my >= 0 && my < r && mx >= 0 && mx < c && arr[my][mx] === ".") {
          jIndex.push([my, mx, count + 1]);
          arr[my][mx] = "J";
        } else if (my >= r || my < 0 || mx < 0 || mx >= c) {
          // 탈출
          answer = count + 1;
          return;
        }
      });
    }

    if (answer !== 0) break;

    // 불의 이동
    let fireLen = fireIndex.length;
    for (let i = 0; i < fireLen; i++) {
      let [fy, fx] = fireIndex.shift();
      move.forEach((m) => {
        let my = fy + m[0];
        let mx = fx + m[1];
        if (
          my >= 0 &&
          my < r &&
          mx >= 0 &&
          mx < c &&
          arr[my][mx] !== "#" &&
          arr[my][mx] !== "F"
        ) {
          arr[my][mx] = "F";
          fireIndex.push([my, mx]);
        }
      });
    }
  }
};

bfs();

console.log(answer === 0 ? "IMPOSSIBLE" : answer);

 


결론

핵심은 해당 좌표에서 갈 수 있는 경우를 적절히 판단하여 최종 결과를 구하는 문제 -> 안하면 시간초과 날 것 같음

ex. 위의 로직상 불이 이동했을 때 지훈의 좌표가 arr[]상 'J' -> 'F'로 초기화 되었을 때, 더 이상 해당 좌표에서 지훈은 움직일 수 없음

'코딩테스트 > bfs (Breadth-first search)' 카테고리의 다른 글

백준 13265 색칠하기  (1) 2025.02.17
백준 14502 연구소  (0) 2025.02.13
백준 2251 물통  (4) 2025.01.01
'코딩테스트/bfs (Breadth-first search)' 카테고리의 다른 글
  • 백준 13265 색칠하기
  • 백준 14502 연구소
  • 백준 2251 물통
의현
의현
개발은 즐거워
  • 의현
    UIHYEON BLOG
    의현
  • 전체
    오늘
    어제
    • 분류 전체보기 (116)
      • 프론트엔드 (47)
        • JavaScript (47)
        • TypeScript (0)
        • HTML (0)
        • CSS (0)
        • React (0)
      • 프로젝트 (2)
        • Task Flow (2)
      • 코딩테스트 (66)
        • Binary Search (2)
        • bfs (Breadth-first s.. (4)
        • dfs (Deapth-first se.. (1)
        • Greedy (1)
        • Dynamic Programming (1)
        • two pointer (4)
        • 구현 (2)
        • LIS(Longest Increasi.. (0)
        • 문자열 (3)
        • 자료구조 (4)
        • 비트마스크 (2)
        • 수학 (2)
        • 프로그래머스 (40)
  • 인기 글

  • 최근 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
의현
백준 4179 불!
상단으로

티스토리툴바