


N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다. 우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다.
이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으로만 채워진 종이의 개수, 1로만 채워진 종이의 개수를 구해내는 프로그램을 작성하시오.
첫째 줄에 N(1 ≤ N ≤ , N은 꼴)이 주어진다. 다음 N개의 줄에는 N개의 정수로 행렬이 주어진다.
첫째 줄에 -1로만 채워진 종이의 개수를, 둘째 줄에 0으로만 채워진 종이의 개수를, 셋째 줄에 1로만 채워진 종이의 개수를 출력한다.
기본적인 재귀 문제로, 이 문제는 다음과 같이 두개의 경우의 수로 나눌 수 있다.
처음 탐색을 시작한 종이의 크기에 대한 영역에 포함된 숫자가 모두 같은 경우
이때 check_same() 함수를 사용하여 현재 탐색하고자 하는 종이의 크기에 대한 영역에 포함된 숫자를 확인하며, 모두 같은 숫자가 포함된 경우 종이를 자를 필요가 없으므로 한장의 종이로 간주하고 해당 영역에 포함된 숫자에 +1을 한다.
처음 탐색을 시작한 종이의 크기에 대한 영역에 포함된 숫자가 하나라도 다른 경우
이때는 종이를 잘라야하는 경우로, 복잡한 로직 없이 단순히 현재 탐색하고 있는 종이에서 9등분 한 뒤, 더 작은 영역에 대해서 1번을 반복하면 된다.
이때 종이를 나눴을 때, 한 장의 종이의 크기가 1까지 작아졌다면 탐색할 필요없이 그 영역에 해당하는 숫자에 +1을 한다.
def cut(start_x, start_y, size):
if size == 1: # 종이의 한 변의 길이가 1이면 바로 더하기
ans[paper[start_x][start_y]] += 1
return
# 해당 영역의 숫자가 모두 같으면 더하기
if check_same(start_x, start_y, size):
ans[paper[start_x][start_y]] += 1
return
# 해당 영역의 숫자가 하나라도 다르다면 종이 9등분으로 자르기
else:
for i in range(3):
for j in range(3):
cut(start_x + i * size//3, start_y + j * size//3, size//3)
def check_same(start_x, start_y, size):
start_num = paper[start_x][start_y]
for i in range(start_x, start_x + size):
for j in range(start_y, start_y + size):
if paper[i][j] != start_num:
return False
return True
n = int(input())
paper = [list(map(int, input().split())) for _ in range(n)]
ans = [0, 0, 0]
cut(0, 0, n)
print(ans[-1], ans[0], ans[1], sep='\n')
이 전에 재귀 문제를 조금이라도 다뤄보고, 생각을 조금만 한다면 쉽게 해결할 수 있는 문제였다.
https://www.acmicpc.net/problem/1780