본문 바로가기
백준

[1780] 종이의 개수

by kmyobin 2023. 2. 3.


https://www.acmicpc.net/problem/1780

 

1780번: 종이의 개수

N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다. 우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다. 만약 종이가 모두 같은 수

www.acmicpc.net

 

분할 정복 문제이다.

 

 

재귀 함수를 통해 계속해서 한 변의 길이를 줄여가면서 종이 내부의 숫자가 모두 동일한지 검사한다.

재귀 함수를 진행할 때 필요한 파라미터는 한 변의 길이빨간색 칠한 행/열의 시작점이다.

예시

또한 9개의 종이로 분할해야하므로 재귀 함수 안에 9개의 재귀 함수를 호출하였다.

 

한 변의 길이가 1이면 더 이상 쪼갤 수 없으므로 재귀 함수를 종료하였다.

#include <iostream>
using namespace std;

int N; int A[2188][2188];
int C[3]; // 0 : -1의 개수, 1 : 0의 개수, 2 : 1의 개수

void f(int r, int c, int order) {	
	bool isCorrect = true; 
	int flag = A[r][c];
	for (int i = r; i <= r + order - 1; i++) {
		for (int j = c; j <= c + order - 1; j++) {
			if (A[i][j] != flag) {
				// 종이가 모두 같은 수가 아니라면
				isCorrect = false;
				break;
			}
		}
		if (!isCorrect) break;
	}

	if (isCorrect) {
		C[flag + 1]++;
	}
	else {
		if (order == 1) return; // 더 이상 쪼갤 수 없으므로 끝
		order = order / 3; // 3으로 나눠야 똑같은 크기의 정사각형 9개로 자를 수 있음

		f(r, c, order);
		f(r, c + order, order);
		f(r, c + 2 * order, order);

		f(r + order, c, order);
		f(r + order, c + order, order);
		f(r + order, c + 2 * order, order);

		f(r + 2 * order, c, order);
		f(r + 2 * order, c + order, order);
		f(r + 2 * order, c + 2 * order, order);
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> N;

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

	f(1, 1, N);

	for (int i = 0; i < 3; i++) {
		cout << C[i] << "\n";
	}
}

'백준' 카테고리의 다른 글

[1629] 곱셈  (0) 2023.02.06
[1992] 쿼드트리  (0) 2023.02.04
[5430] AC  (0) 2023.01.31
[1021] 회전하는 큐  (0) 2023.01.30
[1966] 프린터 큐  (0) 2023.01.26

댓글