[백준 1780]종이의 개수 : 분할과 정복

2077 단어 algorithmalgorithm

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

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

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

1. 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다.

# 종이가 모두 같은지 확인하고, 같다면 숫자를 세고 아니면 종이를 자른다
def check(arr):
  # 첫번째 숫자에 대해 확인하기
  tmp = arr[0][0]
  for i in arr:
    for j in i:
      if j != tmp:
        # 다른 숫자가 있으므로 종이를 자른다
        return cut(arr)
  # 모두 같은 숫자이므로 해당 숫자의 개수를 센다
  cnt[tmp] += 1

2. (1)이 아닌 경우에는 종이를 같은 크기의 종이 9개로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다.

# 종이 9분할하기
def cut(m):
  l = len(m)
  # base case : 더이상 분할할 수 없음
  if l == 1:
    # 해당하는 숫자를 세고 종료한다.
    cnt[m[0][0]] += 1
    return
    
  # 종이를 9등분!
  for i in range(0, l, l//3):
    for j in range(0, l, l//3):
      div = []
      for k in m[i:i+l//3]:
        div.append(k[j:j+l//3])
      check(div)

for문을 안쓰면..

m1, m2, m3, m4, m5, m6, m7, m8, m9 = [], [], [], [], [], [], [], [], []
  for i in range(0, l//3):
    m1.append(m[i][:l//3])
  for i in range(0, l//3):
    m2.append(m[i][l//3:l//3*2])
  for i in range(0, l//3):
    m3.append(m[i][l//3*2:])
  for i in range(l//3, l//3*2):
    m4.append(m[i][:l//3])
  for i in range(l//3, l//3*2):
    m5.append(m[i][l//3:l//3*2])
  for i in range(l//3, l//3*2):
    m6.append(m[i][l//3*2:])
  for i in range(l//3*2, l):
    m7.append(m[i][:l//3])
  for i in range(l//3*2, l):
    m8.append(m[i][l//3:l//3*2])
  for i in range(l//3*2, l):
    m9.append(m[i][l//3*2:])

  check(m1)
  check(m2)
  check(m3)
  check(m4)
  check(m5)
  check(m6)
  check(m7)
  check(m8)
  check(m9)

좋은 웹페이지 즐겨찾기