Coding/알고리즘
[알고리즘 TIL] 2667. 단지 번호
kangplay
2025. 2. 19. 11:39
문제
https://www.acmicpc.net/problem/2667

구현 및 설명
이 문제는 그래프 탐색 문제로, 그래프 탐색에 사용할 수 있는 알고리즘으로는 DFS와 BFS가 있다.
BFS는 최단 경로 찾는 데에 효율적이고, DFS는 모든 경우의 수를 탐색하는 데 효율적이므로, 미로의 모든 지점을 순회해야하는 해당 문제에는 DFS를 활용하였다.
DFS를 활용하여 하나의 단지를 끝까지 탐색한 후, 해당 단지의 집의 갯수를 반환하고 새로운 단지를 탐색하도록 하였다.
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class Q2667_단지번호붙이기 {
static int[] dx = {0, 0, 1, -1};
static int[] dy = {1, -1, 0, 0};
static List<Integer> houseCounts = new ArrayList<>();
static boolean[][] visited;
static int[][] maze;
static LinkedList<Integer[]> stack = new LinkedList<>();
static int N;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
/**
* 미로 초기화
*/
N = Integer.parseInt(br.readLine());
maze = new int[N][N];
visited = new boolean[N][N];
for (int i = 0; i < N; i++) {
String[] inputStr = br.readLine().split("");
for (int j = 0; j < N; j++) {
maze[i][j] = Integer.parseInt(inputStr[j]);
}
}
/**
* DFS로 순회하며 단지 수와 단지에 속하는 집의 수 탐색
*/
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (maze[i][j] == 1 && visited[i][j] == false) {
houseCounts.add(dfs(i, j));
}
}
}
Collections.sort(houseCounts);
bw.write(houseCounts.size() + "\n");
for (int i = 0; i < houseCounts.size(); i++) {
bw.write(houseCounts.get(i) + "\n");
}
bw.flush();
bw.close();
br.close();
}
private static Integer dfs(int y, int x) {
stack.addLast(new Integer[]{x, y});
int houseCount = 0;
while (!stack.isEmpty()) {
Integer[] peekPos = stack.getLast();
stack.removeLast();
int peekX = peekPos[0];
int peekY = peekPos[1];
if (maze[peekY][peekX] == 0 || visited[peekY][peekX] == true) continue;
houseCount++;
visited[peekY][peekX] = true;
for (int i = 0; i < 4; i++) {
int nextX = peekX + dx[i];
int nextY = peekY + dy[i];
if (nextX >= 0 && nextY >= 0 && nextX < N && nextY < N) {
stack.addLast(new Integer[]{nextX, nextY});
}
}
}
return houseCount;
}
}
느낀 점
BFS, DFS 문제에서 항상 고민되는 부분이 갯수 세기이다. BFS의 경우에는 최단 경로 구하기, DFS 경우에는 연결된 덩어리의 갯수를 구하는 경우에 count를 어느 경우에 갱신하여 result 배열에 저장해야하는지 헷갈렸다. 이 문제를 통해서 DFS에서는 한 묶음을 다 돌았을 때 count를 0부터 다시 시작하고, BFS에서는 Queue에 count를 같이 저장하여 for문을 돌며 nextX, nextY를 Queue에 저장하는 시점에 count를 갱신하면 된다. 다른 문제에서도 적용해보며 익숙해질 때까지 연습해봐야겠다.