
https://www.acmicpc.net/problem/1780
문제
N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다. 우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다.
만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다.
(1)이 아닌 경우에는 종이를 같은 크기의 종이 9개로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다.
이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으로만 채워진 종이의 개수, 1로만 채워진 종이의 개수를 구해내는 프로그램을 작성하시오.
입력
첫째 줄에 N(1 ≤ N ≤ 37, N은 3k 꼴)이 주어진다. 다음 N개의 줄에는 N개의 정수로 행렬이 주어진다.
출력
첫째 줄에 -1로만 채워진 종이의 개수를, 둘째 줄에 0으로만 채워진 종이의 개수를, 셋째 줄에 1로만 채워진 종이의 개수를 출력한다.
예제

조건
- 시간 제한: 2초
- 메모리 제한: 256MB
코드
import sys
input = sys.stdin.readline
def DAC(x,y,n):
global minusPaper, zeroPaper, onePaper
first = papers[x][y]
for i in range(x,x+n):
for j in range(y,y+n):
if papers[i][j] != first:
for k in range(3):
for l in range(3):
DAC(x+k*n//3, y+l*n//3, n//3)
return
if first == -1:
minusPaper += 1
elif first == 0:
zeroPaper += 1
else:
onePaper += 1
N = int(input())
papers = [list(map(int,input().split())) for _ in range(N)]
minusPaper, zeroPaper, onePaper = 0, 0, 0
DAC(0,0,N)
print(minusPaper, zeroPaper, onePaper, sep='\n')
- 이 문제는 분할정복을 사용하여 해결할 수 있다. 분할정복은 DFS의 개념과 비슷하다.
- 구간 안에서의 가장 첫 번째 종이
first를 기준으로 삼는다.
- 반복을 하면서, 구간 안에서
first와 다른 종이가 발견되면, 다시 9등분으로 쪼개 탐색을 시작한다.
- 탐색 완료, 즉 같은 종이들로만 이루어져있으면
first를 기준으로minusPaper,zeroPaper,onePaper에 더해준다.
- 구간을 설정하는 것이 가장 헷갈리고 중요한 문제이다.
느낀 점 & 배운 점