알고리즘

백준 2630번 : 색종이 만들기 / C++

도우 2024. 3. 5. 18:09
728x90

 

 

전체 종이의 크기가 N x N (N= 2^7, k는 1 이상 7 이하의 자연수)이며

종이를 가로 세로 중간 부분을 잘라서 똑같은 크기의 네 개의 N/2 x N/2 색종이로 나눈다.

 

색종이는 하나의 색으로만 이루어져 있으므로, 하얀색 또는 파랑색으로만 이루어져 있다면 더 이상 탐색은 필요하지 않다.

 

하지만 탐색을 진행하면서 다른 색이 나오면 탐색을 중지하고, "현재 사각형의 변의 길이 / 2"로 잘라서 탐색을 다시 진행한다.

 

색종이가 좌표 위의 원점에 있다고 가정하고, 한 변의 길이는 N, 시작 좌표는 x, y로 설정한다.

=> [ X 좌표 , Y 좌표, 현재 사각형의 한 변의 길이 ]

 

색종이를 자를때 마다 4개의 사각형이 나오기 때문에 좌표를 수식으로 나타내면 다음과 같다

  • (x , y , N/2)
  • (x + N/2 , y , N/2)
  • (x , y + N/2, N/2)
  • (x + N/2, y + N/2 , N/2)

재귀 호출하여 색종이를 더 이상 자를 수 없을 때까지 반복하여 색종이의 개수를 각각 카운트 한다.

 

 

전체 소스 코드 ▼

#include <iostream>
using namespace std;

int paper[129][129];
int N = 0, white =0 , blue = 0;

void input() {
	cin >> N;

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> paper[i][j];
		}
	}
}

void Find(int x, int y, int z) {
	bool cut = false; // 색종이를 잘라야 하는지 판단
	int color = paper[x][y];  // 색종이의 시작점의 색
	for (int i = x; i < x + z; i++) {
		for (int j = y; j < y + z; j++) {
			if (paper[i][j] != color) {  // 탐색을 진행하다가 다른처음과 다른 색이 나올 경우 
				cut = true; // 잘라야함
				break;
			}
		}
	}
	if (cut) {
		Find(x, y, z / 2);
		Find(x, y + z / 2, z / 2);
		Find(x + z / 2, y, z / 2);
		Find(x + z / 2, y + z / 2, z / 2);
	}
	else {
		if (color == 1) blue++;
		else white++;
	}

}

int main() {
	// 1. (x, y, z)
	// 2. (x, y, z/2)
	// 3. (x, y + z/2, z/2)
	// 4. (x + z/2, y, z/2)
	// 5. (x + z/2, y + z/2 , z/2)

	input();

	Find(0, 0, N);

	cout << white << endl << blue;
	return 0;
}
 
 

 

 

728x90