티스토리 뷰
문제 설명
출판사의 편집자인 어피치는 네오에게 컬러링북에 들어갈 원화를 그려달라고 부탁하여 여러 장의 그림을 받았다. 여러 장의 그림을 난이도 순으로 컬러링북에 넣고 싶었던 어피치는 영역이 많으면 색칠하기가 까다로워 어려워진다는 사실을 발견하고 그림의 난이도를 영역의 수로 정의하였다. (영역이란 상하좌우로 연결된 같은 색상의 공간을 의미한다.)
그림에 몇 개의 영역이 있는지와 가장 큰 영역의 넓이는 얼마인지 계산하는 프로그램을 작성해보자.
위의 그림은 총 12개 영역으로 이루어져 있으며, 가장 넓은 영역은 어피치의 얼굴면으로 넓이는 120이다.
입력 형식
입력은 그림의 크기를 나타내는 m과 n, 그리고 그림을 나타내는 m × n 크기의 2차원 배열 picture로 주어진다. 제한조건은 아래와 같다.
- 1 <= m, n <= 100
- picture의 원소는 0 이상 2^31 - 1 이하의 임의의 값이다.
- picture의 원소 중 값이 0인 경우는 색칠하지 않는 영역을 뜻한다.
출력 형식
리턴 타입은 원소가 두 개인 정수 배열이다. 그림에 몇 개의 영역이 있는지와 가장 큰 영역은 몇 칸으로 이루어져 있는지를 리턴한다.
입출력 예
m | n | picture | answer |
6 | 4 | [[1, 1, 1, 0], [1, 2, 2, 0], [1, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 3], [0, 0, 0, 3]] | [4, 5] |
코드
#include <vector>
#include <queue>
using namespace std;
int bfs(int y, int x, int m, int n, vector<vector<int>> &picture)
{
int i, dy, dx;
int d[] = {0, 0, -1, 1};
int target = picture[y][x];
int size = 1;
queue<pair<int, int>> q;
q.push(make_pair(y, x));
picture[y][x] = -1;
while (!q.empty())
{
y = q.front().first;
x = q.front().second;
q.pop();
for (i = 0; i < 4; i++)
{
dy = y + d[i];
dx = x + d[3 - i];
if (dy >= 0 && dy < m && dx >= 0 && dx < n)
{
if (picture[dy][dx] == target)
{
picture[dy][dx] = -1;
q.push(make_pair(dy, dx));
size++;
}
}
}
}
return size;
}
vector<int> solution(int m, int n, vector<vector<int>> picture) {
int number_of_area = 0;
int max_size_of_one_area = 0;
vector<int> answer(2);
int x;
int y;
int size;
y = 0;
while (y < m)
{
x = 0;
while (x < n)
{
if (picture[y][x] > 0)
{
size = bfs(y, x, m, n, picture);
number_of_area++;
max_size_of_one_area = max(size, max_size_of_one_area);
}
x++;
}
y++;
}
answer[0] = number_of_area;
answer[1] = max_size_of_one_area;
return answer;
}
bfs 알고리즘을 사용하여 해결하는 문제이다. bfs 알고리즘은 재귀적으로 호출하지 않고 queue를 사용한다.
그림의 (0, 0)부터 탐색을 시작하여 값이 0이 아니면서 방문되지 않은 곳을 찾으면 bfs를 수행한다. bfs 함수의 리턴 값은 영역의 크기이며, 이 값은 항상 1 이상이므로 함수를 실행할 때마다 number_of_area를 증가시켜 준다. 또한 size가 현재 최댓값보다 큰 경우 최댓값을 갱신해준다.
bfs 함수에서는 target을 그림에서의 현재 위치로 정한다. target으로 이루어지는 영역의 크기에는 현재 위치도 포함되므로 size는 1로 초기화한다. target에 해당하는 영역을 queue에 저장하고, 방문된 곳은 더 이상 고려하지 않기 위해 -1로 표시한다. d 배열을 사용하여 현재 위치를 기준으로 상하좌우에 target이 있는지 검사하여 queue가 비워질 때까지 반복한다.
링크
programmers.co.kr/learn/courses/30/lessons/1829
코딩테스트 연습 - 카카오프렌즈 컬러링북
6 4 [[1, 1, 1, 0], [1, 2, 2, 0], [1, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 3], [0, 0, 0, 3]] [4, 5]
programmers.co.kr
inbdni/Programmers
Contribute to inbdni/Programmers development by creating an account on GitHub.
github.com
'Coding Test > Programmers' 카테고리의 다른 글
[프로그래머스] 위장 / C++ (0) | 2020.12.31 |
---|---|
[프로그래머스] 주식가격 / C++ (0) | 2020.12.31 |
[프로그래머스] 구명보트 / C++ (0) | 2020.12.31 |
[프로그래머스] 삼각 달팽이 / C++ (0) | 2020.12.29 |
[프로그래머스] 큰 수 만들기 / C++ (0) | 2020.12.29 |