본문 바로가기
알고리즘/백준 - 골드

백준 4179 불!

by 호롤롤로루야 2021. 9. 3.

백준 4179 불!

1. 문제 링크

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

 

4179번: 불!

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

www.acmicpc.net

 

2. 문제 해결에 대한 아이디어

1. Input에서 지훈이의 위치와 불의 위치를 각각 jQ, fQ에 저장한다. --> BFS를 하기 위함

2. 한 턴마다 지훈이와 불이 움직인다.

3. 지훈이는  jMove 불은 fireMove로 각각 구현했다.

   . 나는 지훈이를 먼저 움직이고 그다음에 불을 확산시켰다.

   . n+1번째 턴에 지훈이가 있을 수 있는 위치(이동 전) 중, n번째 턴에 불이 위치한 곳은 제외시켰다.

   . 이동할 수 있는 공간이 없다면, jMove에서 jQ의 크기가 0일 것이다.

   . 탈출하게 된다면 지훈이의 위치는 배열을 벗어난 위치일 것이다.

 

3. 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
	static char[][] board;
	static boolean[][] visited;
	static int[] dirY = { 0, 0, 1, -1 };
	static int[] dirX = { 1, -1, 0, 0 };
	static Queue<Pair> jQ = new LinkedList<>();
	static Queue<Pair> fQ = new LinkedList<>();
	static int R, C, count = 0;

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String[] rc = br.readLine().split(" ");

		R = Integer.parseInt(rc[0]);
		C = Integer.parseInt(rc[1]);

		board = new char[R][C];
		visited = new boolean[R][C];

		for (int i = 0; i < R; i++) {
			String line = br.readLine();
			for (int j = 0; j < C; j++) {
				board[i][j] = line.charAt(j);
				if (board[i][j] == 'J')
					jQ.add(new Pair(i, j));
				else if (board[i][j] == 'F')
					fQ.add(new Pair(i, j));
			}
		}

		while (true) {
			count++;
			int status = jMove();

			if (status == 1) {
				System.out.println(count);
				return;
			} else if (status == -1) {
				System.out.println("IMPOSSIBLE");
				return;
			} else {
				fireMove();
			}
		}
	}

	static int jMove() {

		Queue<Pair> tempQ = new LinkedList<>();

		while (!jQ.isEmpty()) {
			Pair now = jQ.poll();
			int y = now.y;
			int x = now.x;
			if (board[y][x] == 'F')
				continue;
			visited[y][x] = true;

			for (int i = 0; i < 4; i++) {
				int yy = y + dirY[i];
				int xx = x + dirX[i];

				// 탈출한 경우
				if (yy < 0 || xx < 0 || yy >= R || xx >= C)
					return 1;

				if (board[yy][xx] == '#' || board[yy][xx] == 'F' || visited[yy][xx])
					continue;
				visited[yy][xx] = true;
				board[yy][xx] = 'J';
				tempQ.add(new Pair(yy, xx));
			}

		}
		// 사방이 불이거나 벽일 경우에는 이동하지 못 했기 때문에 tempQ는 비어있다.
		if (tempQ.isEmpty())
			return -1;

		// 정상적으로 이동한 경우
		jQ = tempQ;
		return 0;
	}

	static void fireMove() {
		Queue<Pair> tempQ = new LinkedList<>();
		while (!fQ.isEmpty()) {
			Pair now = fQ.poll();
			int y = now.y;
			int x = now.x;
			for (int i = 0; i < 4; i++) {
				int yy = y + dirY[i];
				int xx = x + dirX[i];

				if (yy < 0 || xx < 0 || yy >= R || xx >= C 
						|| board[yy][xx] == '#' || board[yy][xx] == 'F')
					continue;
				board[yy][xx] = 'F';
				tempQ.add(new Pair(yy, xx));

			}
		}

		fQ = tempQ;
	}
}

class Pair {
	int y, x;

	public Pair(int y, int x) {
		super();
		this.y = y;
		this.x = x;
	}
}
 

4. 채점 결과

 

5. 느낀 점

1. 지훈이와 불이 한 턴에 모두 움직여야 하는 부분에서 누가 먼저 움직일 것인지를 고민했다.

2. 예시로 주어진 입력에서 지훈이와 불이 붙어있는 경우 불이 먼저 움직이면 구현이 힘들 것이라고 생각했다.

3. 따라서 지훈이를 먼저 이동시키고 그 후 불을 이동시켰다.

4. 처음에는 지훈이가 이동할 수 있는 위치에 마킹한 후 불이 그 위치에 도달할 거라는 생각을 못해 조금 헤맸다.

 

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

백준 2174 로봇 시뮬레이션  (0) 2021.09.07
백준 2573 빙산  (0) 2021.09.05
백준 2589 보물섬  (0) 2021.09.02

댓글