https://www.acmicpc.net/problem/16946
1. 아이디어
각 위치에서 해당 벽을 부쉈을 때 이동할 수 있는 칸 즉 0의 개수를 세는 문제로 BFS를 활용하면 해결할 수 있다.
2. 문제풀이
기본 흐름은 입력을 받아서 2차원 배열로 맵을 표현한 후 BFS를 돌았다. BFS는 이동할 수 있는 칸을 발견하면 연결된 모든 이동할 수 있는 칸의 개수를 세서 경계가 됐던 벽에 더해주는 방식으로 구현했다. 이를 위해 두 개의 Queue를 활용해서 하나는 이동할 수 있는 칸, 하나는 경계가 되는 벽들을 넣었고 둘 다 같은 방문 체크 배열로 방문 체크를 해줬다. 이동할 수 있는 칸에 대한 BFS로 이동할 수 있는 칸의 개수를 세주며 경계를 만나면 경계는 따로 Queue에 넣어줬고, 이후 경계를 담은 Queue에서 하나씩 꺼내서 더해준 후 경계에 대한 방문 체크를 풀어주는 방식으로 구현했다. 하나의 경계가 중복해서 더해질 수 있어서 경계에 대한 방문 체크를 해줘야하며 하나의 경계가 서로 다른 이동할 수 있는 칸의 영역을 마주볼 수 있어서 방문 체크를 다시 풀어줘야 한다.
3. 코드
import java.io.*;
import java.util.*;
public class Main {
private static class Node {
int r;
int c;
public Node(int r, int c) {
this.r = r;
this.c = c;
}
}
private static final int[] dr = {-1, 0, 1, 0};
private static final int[] dc = {0, 1, 0, -1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringBuilder sb = new StringBuilder();
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[][] map = new int[N][M];
for (int i = 0; i < N; i++) {
char[] input = br.readLine().toCharArray();
for (int j = 0; j < M; j++) {
map[i][j] = Character.getNumericValue(input[j]);
}
}
boolean[][] visited = new boolean[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 0 && !visited[i][j]) {
bfs(i, j, N, M, map, visited);
}
}
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
sb.append(map[i][j] % 10);
}
sb.append("\n");
}
bw.write(sb.toString());
bw.flush();
}
private static void bfs(int r, int c, int N, int M, int[][] map, boolean[][] visited) {
Queue<Node> q = new ArrayDeque<>();
q.offer(new Node(r, c));
visited[r][c] = true;
Queue<Node> edges = new ArrayDeque<>();
int cnt = 1;
while (!q.isEmpty()) {
Node node = q.poll();
for (int dir = 0; dir < 4; dir++) {
int nr = node.r + dr[dir];
int nc = node.c + dc[dir];
if (nr < 0 || nr >= N || nc < 0 || nc >= M) continue;
if (visited[nr][nc]) continue;
if (map[nr][nc] == 0) {
q.offer(new Node(nr, nc));
cnt++;
} else {
edges.offer(new Node(nr, nc));
}
visited[nr][nc] = true;
}
}
while (!edges.isEmpty()) {
Node node = edges.poll();
map[node.r][node.c] += cnt;
visited[node.r][node.c] = false;
}
}
}
4. 후기
'코딩테스트 준비 > 백준' 카테고리의 다른 글
[백준] 5014번 - 스타트링크 [Java] (0) | 2025.01.20 |
---|---|
[백준] 1600번 - 말이 되고픈 원숭이 [Java] (1) | 2025.01.20 |
[백준] 16933번 - 벽 부수고 이동하기 3 [Java] (0) | 2025.01.20 |
[백준] 14442번 - 벽 부수고 이동하기 2 [Java] (0) | 2025.01.20 |
[백준] 2206번 - 벽 부수고 이동하기 [Java] (0) | 2025.01.20 |