백준 No.2603 [색종이 만들기]
본문 바로가기
Algorithm (C++ based)/BOJ

백준 No.2603 [색종이 만들기]

by 조훈이 2021. 1. 24.

// Baekjoon Online Judge No.2630 [색종이 만들기]


   Code   

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <vector>
#define DEVIDING_STANDARD 2
 
using namespace std;
 
int N;
vector<vector<int>> paper;
// 1 is blue, 0 is white
 
int blue = 0;
int white = 0;
 
void DC(int len, int x, int y) { // len 길이의 block이 들어왔고, 이제 곧 쪼갤거다. (길이가 1일때 제외)
    if (len == 1) { // 더이상 나눌 수 없을 때
        if (paper[y][x]) blue++;
        else white++;
 
        return;
    }
 
    int div = len / 2;
    int initial_color = paper[y][x];
    int yVal = y, xVal = x;
 
    for (int j = yVal; j < yVal + len; j++) {
        for (int i = xVal; i < xVal + len; i++) {
            if (paper[j][i] != initial_color) goto devide; // 쪼개야 하므로 쪼개는 for문으로 gogo!
            if (j == yVal + len - 1 && i == xVal + len - 1) { // 현재 block에 color가 다 똑같을 경우
                if (initial_color) blue++;
                else white++;
 
                return;
            }
        }
    }
    
    devide:
 
    for (int j = 0; j < DEVIDING_STANDARD; j++) { // 쪼개는 for문
        for (int i = 0; i < DEVIDING_STANDARD; i++) {
            DC(div, x + div * i, y + div * j); // devide it
        }
    }
}
 
/* normal devide and conquer 는 1 조각까지 쪼개버리지만
 * 이 문제에서는 쪼개지 않는 조건이 필요.
 *    -> 한 block 이 same color 일때.
 */
 
int main() {
    cin >> N;
    paper.assign(N, vector<int>(N, 0));
 
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> paper[i][j];
 
    DC(N, 00);
 
    cout << white << '\n' << blue;
}
cs

   How to solve   

  기존 분할 정복 문제의 형태에 더이상 쪼개지지 않을 조건 을 부여해야하는 문제였다. 또한 이 문제에서 더이상 쪼개지지 않을 조건은, 한 블럭에 해당하는 종이들의 색상이 모두 똑같은 경우이다. (이 문제에서 한 블럭의 크기는 2*2, 4*4, 등등이 될 수 있다.) 

 

  DC 함수에 입력되는 변수들에는 현재 탐색하는 블럭의 길이 ( initial_color ), 탐색을 시작할 좌표 ( int x, int y ) 가 들어가있다. 이 정보들을 토대로 현재 DC함수 내에서 체킹할 영역을 알 수 있을 것이다. 26번째 ~ 38번째 line에서 그 체킹할 영역에 해당하는 색종이의 색들이 다 같은지 아닌지 검사를 한다. 처음에 입력되는 변수인 x, y 값을 활용하여 첫 좌표의 색종이 색 변수를 만든다. (23번째 line 에  int initial_color; ) for문을 계속 돌면서 하나하나 해당 위치에 해당하는 색종이의 색이  initial_color  와 다른지 검사를 한다.

 

  만약 검사 도중 initial_color 와 다른 부분이 하나라도 발견이 되면 28번째 line에 따라 38번째 line에 있는 devide: 로 goto 한다. 체킹하던 영역의 색종이들의 색이 전부 같지 않다는걸 알게됐으니 쪼개야하기 때문이다.

 

  29번째 ~ 33번째 line은 for문을 돌면서 28번째 line에 한번도 걸리지 않고 for문의 끝자락까지 왔을때의 경우이다. 즉 체킹하던 영역의 색종이들의 색이 모두 같을때를 의미한다.  initial_color  를 토대로  initial_color 의 색이 즉 현재 영역의 색종이들의 색일 것이므로  initial_color  가 1인 경우 (파랑색)  blue++;  를,  initial_color  가 0인 경우 (흰색)  white++;  를 해준다. 그 후 더이상 쪼갤 필요가 없으므로  return;  을 진행한다. 그러면 이제 더이상 쪼개지 않고 이전에 쪼개던 영역을 쪼개기 시작할 것이다.

728x90

'Algorithm (C++ based) > BOJ' 카테고리의 다른 글

백준 No.11049 [행렬 곱셈 순서]  (0) 2021.02.04
백준 No.1912 [연속합]  (0) 2021.02.02
백준 No.2447 [별 찍기 - 10]  (0) 2021.01.24
백준 No.10757 [큰 수 A+B]  (0) 2021.01.05
백준 No.10844 [쉬운 계단 수]  (0) 2020.11.18

댓글