[ Algorithm ]/Programmers
[프로그래머스] 카카오프렌즈 컬러링북
HoYoung Kim
2022. 6. 2. 17:56
문제 설명
출판사의 편집자인 어피치는 네오에게 컬러링북에 들어갈 원화를 그려달라고 부탁하여 여러 장의 그림을 받았다. 여러 장의 그림을 난이도 순으로 컬러링북에 넣고 싶었던 어피치는 영역이 많으면 색칠하기가 까다로워 어려워진다는 사실을 발견하고 그림의 난이도를 영역의 수로 정의하였다. (영역이란 상하좌우로 연결된 같은 색상의 공간을 의미한다.)
그림에 몇 개의 영역이 있는지와 가장 큰 영역의 넓이는 얼마인지 계산하는 프로그램을 작성해보자.
위의 그림은 총 12개 영역으로 이루어져 있으며, 가장 넓은 영역은 어피치의 얼굴면으로 넓이는 120이다.
풀이
사용 언어 : Java
- 그림의 영역(board), 방문 체크(visited) 배열 생성
- BFS 활용 : 이전 좌표, 현재 좌표 비교해서 각 색깔별 영역의 갯수와 가장 큰 영역의 크기를 구한다.
넓이 우선 탐색(BFS)을 이용한 문제이다.
BFS의 개념만 알고 있다면 그렇게 어려운 문제는 아닌 것 같다.
깊이 우선 탐색(DFS)를 이용해도 되겠지만, 경우에 따라서 시간이 오래 걸릴 수 있으므로 BFS를 채택했다.
코드
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
class Solution {
int numberOfArea; // 영역의 갯수
int maxSizeOfOneArea; // 가장 큰 영역의 크기
int M, N;
int[][] board;
boolean[][] visited;
public int[] solution(int m, int n, int[][] picture) {
numberOfArea = 0;
maxSizeOfOneArea = 0;
M = m;
N = n;
board = new int[M][N];
visited = new boolean[M][N];
for (int i = 0; i < M; i++) {
if (N >= 0) {
System.arraycopy(picture[i], 0, board[i], 0, N);
}
}
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (!visited[i][j] && board[i][j] != 0) { // 처음 방문 && 색칠된 영역
maxSizeOfOneArea = Math.max(maxSizeOfOneArea, bfs(i, j));
numberOfArea++;
}
}
}
return new int[]{numberOfArea, maxSizeOfOneArea};
}
private int bfs(int x, int y) {
int[] dx = {0, 0, -1, 1}; // 상, 하, 좌, 우
int[] dy = {-1, 1, 0, 0};
int count = 1;
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[]{x, y});
visited[x][y] = true;
while (!queue.isEmpty()) {
int[] cur = queue.poll(); // 현재 좌표
int curX = cur[0];
int curY = cur[1];
for (int i = 0; i < 4; i++) {
int nx = dx[i] + curX;
int ny = dy[i] + curY;
if (nx >= 0 && nx < M && ny >= 0 && ny < N) { // 옮긴 좌표가 board 내부인지 검사
if (!visited[nx][ny] && board[nx][ny] == board[curX][curY]) { // 처음 방문 && 이전 좌표와 같은 색인지 검사
visited[nx][ny] = true;
queue.add(new int[]{nx, ny});
count++;
}
}
}
}
return count;
}
}