[알고리즘 풀이 분석] 프로그래머스 카카오프렌즈 컬러링북 (2017 카카오코드 예선)

지난 목요일부터 월요일까지 5일동안 자소서 + 코테 준비 + 카카오, 네웹 코테 + 백신접종 의 폭풍같은 5일을 보내고 오늘 오후까지 잘 놀고 잘 쉬었다..!

다시 달리기 전 오늘은 간단한 문제를 하나 풀어보았다.
기본적인 문제였기 때문에 c++, swift 를 모두 이용해서 풀어보았다.
네웹 코테 당시 검색, IDE 모두 사용 불가했고 c++ 마저 옵션에 없었다.. 나는 결국 swift로 풀어야 했는데 이틀 전부터 급하게 swift 사용을 익혀서 풀긴 풀었는데 확실히 익숙하지 않다보니 오래 걸렸고,, 3개중에 2솔밖에 못했다 ㅜ 그것도 완탐으로,,,,ㅎㅎ

오늘부터는 swift 도 동시에 연습할 생각이다
그리고 가능하면 IDE 사용하지 않고!!

그래서 오늘 풀어본 문제는 프로그래머스 카카오프렌즈 컬러링북 이다!




프로그래머스 카카오프렌즈 컬러링북

카카오 프렌즈 컬러링북

출판사의 편집자인 어피치는 네오에게 컬러링북에 들어갈 원화를 그려달라고 부탁하여 여러 장의 그림을 받았다. 여러 장의 그림을 난이도 순으로 컬러링북에 넣고 싶었던 어피치는 영역이 많으면 색칠하기가 까다로워 어려워진다는 사실을 발견하고 그림의 난이도를 영역의 수로 정의하였다. (영역이란 상하좌우로 연결된 같은 색상의 공간을 의미한다.)

그림에 몇 개의 영역이 있는지와 가장 큰 영역의 넓이는 얼마인지 계산하는 프로그램을 작성해보자.

위의 그림은 총 12개 영역으로 이루어져 있으며, 가장 넓은 영역은 어피치의 얼굴면으로 넓이는 120이다.




입출력

입력은 그림의 크기를 나타내는 m과 n, 그리고 그림을 나타내는 m × n 크기의 2차원 배열 picture로 주어진다. 제한조건은 아래와 같다.

  • 1 <= m, n <= 100
  • picture의 원소는 0 이상 2^31 - 1 이하의 임의의 값이다.
  • picture의 원소 중 값이 0인 경우는 색칠하지 않는 영역을 뜻한다.

리턴 타입은 원소가 두 개인 정수 배열이다. 그림에 몇 개의 영역이 있는지와 가장 큰 영역은 몇 칸으로 이루어져 있는지를 리턴한다.


mnpictureanswer
64[[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]



나의 풀이

간단한 BFS/DFS 문제이다.
재귀를 이용해서 구현했으며 나는 BFS 를 선택하였다.

색칠 되어 있고 방문하지 않은 칸을 발견할 때마다 영역 수를 올려주고 재귀적으로 동일한 색상의 영역을 찾아간다. 매개변수로 넘긴 영역 크기 변수를 올려주면서 하나의 영역 탐색이 끝나면 최대 영역 넓이와 비교해 갱신하였다.

swift 에선 call by reference 를 어떻게 사용하나 했는데 inout 를 사용해주면 된다고 한다. 이게 swift 에서 자연스러운 방법인지는 좀 더 알아봐야 할 것 같다.




코드

cpp

#include <vector>

using namespace std;

int dy[4] = {-1,0,1,0};
int dx[4] = {0,1,0,-1};

int M;
int N;
vector<vector<int>> map;

void bfs(vector<vector<bool>> & visited, int r, int c, int & size, int color){

    for(int i=0; i<4; i++){
        int nr = r + dy[i];
        int nc = c + dx[i];

        if(nr>=0 && nr<M && nc>=0 && nc<N && map[nr][nc] == color && !visited[nr][nc]){
            visited[nr][nc] = true;
            size++;
            bfs(visited, nr, nc, size, color);
        }
    }

    return;
}
vector<int> solution(int m, int n, vector<vector<int>> picture) {
    int number_of_area = 0;
    int max_size_of_one_area = 0;

    map = picture;
    vector<vector<bool>> visited(m, vector<bool>(n, false));

    M = m;
    N = n;

    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            if(picture[i][j] > 0 && !visited[i][j]){
                number_of_area++;
                visited[i][j] = true;
                int size = 1;
                bfs(visited, i, j, size, picture[i][j]);
                if(max_size_of_one_area < size) max_size_of_one_area = size;
            }
        }
    }

    vector<int> answer = {number_of_area, max_size_of_one_area};
    return answer;
}


swift

import Foundation

var M = 0
var N = 0
var map = [[Int]]()

let dy = [-1,0,1,0]
let dx = [0,1,0,-1]

func bfs(visited : inout [[Bool]], r : Int, c : Int, size : inout Int, color : Int ) -> Void {
    for i in 0..<4 {
        let nr = r + dy[i]
        let nc = c + dx[i]
        
        if nr>=0 && nr<M && nc>=0 && nc<N && !visited[nr][nc] && map[nr][nc]==color {
            visited[nr][nc] = true
            size += 1
            bfs(visited: &visited, r: nr, c: nc, size: &size, color: color)
        }
    }
}

func solution(_ m : Int, _ n : Int, _ picture : [[Int]]) -> [Int]{
    var number_of_area = 0
    var max_size_of_one_area = 0
    let row = [Bool](repeating: false, count: n)
    var visited = [[Bool]](repeating: row, count:m)
    
    map = picture
    M = m
    N = n
    
    for i in 0..<m {
        for j in 0..<n {
            if picture[i][j]>0 && !visited[i][j] {
                number_of_area += 1
                visited[i][j] = true
                var size = 1
                bfs(visited: &visited, r: i, c: j, size: &size, color: picture[i][j])
                if max_size_of_one_area < size {
                    max_size_of_one_area = size
                }
            }
        }
    }
    
    return [number_of_area, max_size_of_one_area]
}

좋은 웹페이지 즐겨찾기