백준 2630 - 색종이 만들기 [C++]

2022. 1. 1. 15:25프로그래밍/PS

새해 기념 첫번째 포스팅입니다.

작년 KOI 중등부 첫번째 문제도 비슷했던 것으로 기억이 나는데, 이 문제가 좀 더 쉬웠던 것 같습니다.

문제의 목표는 자른 색종이가 전부 하얀색이거나 파란색이 될때까지 색종이를 반으로 계속 자르고 나서 그 잘라진 하얀색 / 파란색 색종이의 개수를 구하는 것입니다. 


#풀이

한 변의 길이가 모두 2의 거듭제곱 형태이기 때문에, 좌표를 바꾸고 길이를 계속 절반으로 하는 재귀함수를 구현하면 될 것 같습니다.

구체적으로는,

1. N x N 사이즈의 정사각형 내에 있는 모든 칸의 색을 체크합니다.

2 - 1. 만약 모든 색이 같다면, 해당 색의 색종이 개수에 1을 더해줍니다.

2 - 2. 만약 한 칸이라도 색이 다르다면, N x N 사이즈의 색종이를 위 그림처럼 (N/2) x (N/2) 사이즈의 색종이 4개로 잘라서 1번부터 반복하고 종료해줍니다.

* 종료를 안하면 색종이가 한 색깔이 아니여도 색깔의 개수를 올려주므로 반드시 종료해줘야 합니다.

 

1 x 1 사이즈의 색종이에서는 반드시 그 칸의 색이 곧 해당 색종이의 색이기 때문에, 다른 조건을 넣을 필요는 없습니다.


#코드

 

#include <stdio.h>

const int N = (1e2 + 1) * 2;

int n = 0, w = 0, b = 0;//w = 하얀색 색종이 개수, b = 파란색 색종이 개수
int mapp[N][N] = {{0}};

void paper(int x, int y, int l);//하얀색, 파란색 색종이의 개수를 구할 재귀함수

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j)
            scanf("%d", &mapp[i][j]);
    }
    paper(0, 0, n);
    printf("%d\n%d", w, b);
    return 0;
}

void paper(int x, int y, int l) {//l = 색종이의 한 변의 길이
    int newlen = l / 2;
    bool def = mapp[x][y];//현재 색종이의 맨 왼쪽 위 칸의 색
    for (int i = x; i < x + l; ++i) {
        for (int j = y; j < y + l; ++j) {
            if (mapp[i][j] != def) {//한 칸이라도 색이 다르면 색종이를 4개로 자름
                paper(x, y, newlen);
                paper(x + newlen, y, newlen);
                paper(x, y + newlen, newlen);
                paper(x + newlen, y + newlen, newlen);
                return;
            }
        }
    }
    //모든 칸의 색이 같으면 그 색의 개수를 올려줌
    if (def == 0)
        ++w;
    else
        ++b;
}

 

'프로그래밍 > PS' 카테고리의 다른 글

백준 2467 - 용액 [C++]  (2) 2024.01.05
백준 1629 - 곱셈 [C++]  (0) 2022.02.28