티스토리 뷰
문제 설명
출판사의 편집자인 어피치는 네오에게 컬러링북에 들어갈 원화를 그려달라고 부탁하여 여러 장의 그림을 받았다. 여러 장의 그림을 난이도 순으로 컬러링북에 넣고 싶었던 어피치는 영역이 많으면 색칠하기가 까다로워 어려워진다는 사실을 발견하고 그림의 난이도를 영역의 수로 정의하였다. (영역이란 상하좌우로 연결된 같은 색상의 공간을 의미한다.)
그림에 몇 개의 영역이 있는지와 가장 큰 영역의 넓이는 얼마인지 계산하는 프로그램을 작성해보자.
위의 그림은 총 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] |
예제에 대한 설명
예제로 주어진 그림은 총 4개의 영역으로 구성되어 있으며, 왼쪽 위의 영역과 오른쪽의 영역은 모두 1로 구성되어 있지만 상하좌우로 이어져있지 않으므로 다른 영역이다. 가장 넓은 영역은 왼쪽 위 1이 차지하는 영역으로 총 5칸이다.
풀이 방법
dfs 알고리즘 방식으로 문제를 해결합니다.
주어진 모든 블록을 순회하며 영역의 개수 및 최대 영역의 크기를 구합니다.
단, 이미 다녀온 블록은 다시 순회하지 않아야 시간도 단축될 뿐더러 무한 루프를 돌지 않습니다.
이미 다녀오지 않았으면서 값이 0이 아닌 블록을 대상으로 상하좌우 탐색을 합니다.
현재 위치한 블록의 값이 윗 블록의 값과 일치하고 윗 블록을 다녀오지 않았다면, 윗 블록으로 옮겨가 영역의 크기를 1 높힌 후 다시 상하좌우 탐색을 합니다.
윗 블록 뿐만이 아니라 아래, 왼쪽, 오른쪽 블록도 탐색 대상이 됩니다.
한 블록으로부터 파생된 탐색이 끝나면, 해당 영역의 크기 조사가 마쳐졌으므로 최대 영역의 크기와 비교합니다.
영역 크기 조사가 마쳐질 때 마다 최대 영역의 크기와 비교함으로써, 최종 최대 영역 크기를 산출합니다.
* dfs 알고리즘에 대한 설명은 아래 게시물을 참고해주세요.
https://dvpzeekke.tistory.com/37?category=887119
[c++] DFS(Depth First Search) 알고리즘
BFS 알고리즘은 깊이를 우선으로 탐색하는 알고리즘 입니다. 즉, 현재 정점에 갈 수 있는 노드까지 들어가며 탐색합니다. 주로 stack 혹은 재귀함수를 이용해서 구현합니다. c++로 dfs를 구현해보겠습니다. 위..
dvpzeekke.tistory.com
풀이
#include <vector>
using namespace std;
vector<vector<bool>> isChecked;
int number_of_area;
int max_size_of_one_area;
int size_of_one_area;
void checkNear(int i, int j, int m, int n, vector<vector<int>> &picture) {
isChecked[i][j] = true;
size_of_one_area++;
// 위 탐색
if (i > 0) {
if ((picture[i][j] == picture[i - 1][j]) && (!isChecked[i - 1][j])) {
checkNear(i - 1, j, m, n, picture);
}
}
// 아래 탐색
if (i < m - 1) {
if ((picture[i][j] == picture[i + 1][j]) && (!isChecked[i + 1][j])) {
checkNear(i + 1, j, m, n, picture);
}
}
//왼쪽 탐색
if (j > 0) {
if ((picture[i][j] == picture[i][j - 1]) && ((!isChecked[i][j - 1]))) {
checkNear(i, j - 1, m, n, picture);
}
}
// 오른쪽 탐색
if (j < n - 1) {
if ((picture[i][j] == picture[i][j + 1]) && (!isChecked[i][j + 1])) {
checkNear(i, j + 1, m, n, picture);
}
}
}
// 전역 변수를 정의할 경우 함수 내에 초기화 코드를 꼭 작성해주세요.
vector<int> solution(int m, int n, vector<vector<int>> picture) {
vector<int> answer(2);
isChecked.assign(m, vector<bool> (n, false));
number_of_area = 0;
max_size_of_one_area = 0;
size_of_one_area = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (isChecked[i][j])
continue;
if (picture[i][j] == 0)
continue;
number_of_area++;
size_of_one_area = 0;
checkNear(i, j, m, n, picture);
if (size_of_one_area > max_size_of_one_area)
max_size_of_one_area = size_of_one_area;
}
}
answer[0] = number_of_area;
answer[1] = max_size_of_one_area;
return answer;
}
'Dev.CodingTest > Programmers' 카테고리의 다른 글
[프로그래머스 c++] 2 x n 타일링 (0) | 2020.01.19 |
---|---|
[프로그래머스 c++] 2017 서머코딩 > 소수 만들기 (0) | 2019.11.07 |
[프로그래머스 c++] 2020 KAKAO BLIND RECRUITMENT > 문자열 압축 (2) | 2019.10.27 |
[프로그래머스 c++] 2018 서머코딩 > 숫자 게임 (4) | 2019.10.23 |
[c++ 프로그래머스] 2018 서머코딩 > 영어 끝말잇기 (13) | 2019.10.14 |
- Total
- Today
- Yesterday
- 백준
- 코딩테스트
- 구슬탈출
- 깊이우선탐색
- 서머코딩
- 이진트리
- Xcode
- algorithm
- ec2
- BFS
- 삼성역량테스트
- Swift
- dfs
- 시뮬레이션
- 알고리즘
- Collection
- ios
- dp
- 프로그래머스
- Programmers
- 컬렉션
- aws
- datastructure
- 스위프트
- 호제법
- 자료구조
- count
- SummerCoding
- isempty
- c++
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |