[백준] 1780번 종이의 개수 - Python / 알고리즘 중급 1/3 - 분할 정복 (연습)

ByungJik_Oh·2025년 6월 30일
0

[Baekjoon Online Judge]

목록 보기
177/244
post-thumbnail



💡 문제

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

  1. 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다.
  2. (1)이 아닌 경우에는 종이를 같은 크기의 종이 9개로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다.

이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으로만 채워진 종이의 개수, 1로만 채워진 종이의 개수를 구해내는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 373^7, N은 3k3^k 꼴)이 주어진다. 다음 N개의 줄에는 N개의 정수로 행렬이 주어진다.

출력

첫째 줄에 -1로만 채워진 종이의 개수를, 둘째 줄에 0으로만 채워진 종이의 개수를, 셋째 줄에 1로만 채워진 종이의 개수를 출력한다.


💭 접근

기본적인 재귀 문제로, 이 문제는 다음과 같이 두개의 경우의 수로 나눌 수 있다.

  1. 처음 탐색을 시작한 종이의 크기에 대한 영역에 포함된 숫자가 모두 같은 경우

    이때 check_same() 함수를 사용하여 현재 탐색하고자 하는 종이의 크기에 대한 영역에 포함된 숫자를 확인하며, 모두 같은 숫자가 포함된 경우 종이를 자를 필요가 없으므로 한장의 종이로 간주하고 해당 영역에 포함된 숫자에 +1을 한다.

  2. 처음 탐색을 시작한 종이의 크기에 대한 영역에 포함된 숫자가 하나라도 다른 경우

    이때는 종이를 잘라야하는 경우로, 복잡한 로직 없이 단순히 현재 탐색하고 있는 종이에서 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


profile
精進 "정성을 기울여 노력하고 매진한다"

0개의 댓글