[Baekjoon] 1780, 4779, 1074, 2447 (Divide and Conquer)
1780
https://www.acmicpc.net/problem/1780
import sys
input = sys.stdin.readline
n = int(input())
paper = [list(map(int, input().split())) for _ in range(n)]
cnt = [0]*3
def ans(l, x, y):
tmp = paper[x][y]
for i in range(x,x+l):
for j in range(y,y+l):
if tmp != paper[i][j]:
for a in range(3):
for b in range(3):
ans(l//3,x + a*(l//3),y + b*(l//3))
return
cnt[tmp+1] += 1
ans(n, 0, 0)
print(*cnt, sep = "\n")
point 1
사실 모든 수가 같은 지만 판단하도록 함수를 작성한 후 매개변수를 9분할 구간을 판단할 수록 설정하여 구간마다 재귀를 돌리는 것이 훨씬 시간은 빠를 것 같다. 하지만 긴 코드를 작성하는 것이 귀찮았으므로 ,,, 한 번의 재귀호출로 (코드 상 1번) 처리할 수 있도록 일반화했다.
soltion
paper[x][y]를 기준으로, 주어진 구간의 값이 같지 않다면, 각 구간이 모두 같은 수로 채워질 때까지 9개로 구간을 분할하도록 했다. 주어진 값이 0, 1, -1이므로, cnt 배열의 값을 늘려줄 때 각각의 값을 인덱스로 사용해도 문제가 발생하지 않으나, 출력부를 작성할 때 반복문의 범위를 (-1,2)로 설정해주어야하는 불편함이 있어 cnt 배열에 개수를 저장할 때 tmp+1인 인덱스의 값을 증가시켰다.
4779
https://www.acmicpc.net/problem/4779
import sys
input = sys.stdin.readline
def div(n, li):
if n == 1: return li
l = n//3
return div(l,li[:l]) + " "*l + div(l, li[l*2:])
while True:
n = input().rstrip()
if n == "": break
num = 3**int(n); dash = "-"*num
print(div(num,dash))
1074
https://www.acmicpc.net/problem/1074
def div(size, row, col, cnt):
l = size//2
if r == row and c == col: print(cnt)
elif r < row + l and c < col + l: div(l, row, col, cnt)
elif r < row + l and c >= col + l: div(l, row, col + l, cnt + l**2)
elif r >= row + l and c < col + l: div(l, row + l, col, cnt + (l**2) * 2)
elif r >= row + l and c >= col + l: div(l, row + l, col + l, cnt + (l ** 2) * 3)
n, r, c = map(int, input().split())
div(2**n, 0, 0, 0)
2447
https://www.acmicpc.net/problem/2447
def star(n):
if n == 1: return ['*']
rec = star(n//3); ans = []
for i in rec: ans.append(i*3)
for i in rec: ans.append(i + ' '*(n//3) + i)
for i in rec: ans.append(i*3)
return ans
# print(*star(int(input())), sep = "\n")
print('\n'.join(star(int(input()))))
soltion
구조는 알겠으나 어떻게 재귀로 구현해야할 지 떠올리기 힘들었던 문제. 비어있는 곳의 점화식을 구해 3*3의 별을 채워야하는 곳에 넣어야한다는 생각에서 벗어나는 데에 시간이 오래 걸렸다. n을 3씩 나눠가며 n==1일 될 때까지 재귀를 돌면 필요한만큼 재귀를 돌 수 있다. 이 때 기존에 생성된 rec(초기에는 * 하나)을 모든 구역에 3배로 채워넣으며, 가운데 영역만 비워둘 수 있도록 했다.
*를 사용한 출력이 익숙하여 위 코드에서 주석처리된 출력문을 사용했는데, join을 사용하는 것이 시간이 더 빠르다. join을 사용하는 데에 익숙해져야겠다