728x90
#1780번 종이의 개수 https://www.acmicpc.net/problem/1780
1780번: 종이의 개수
N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1 중 하나가 저장되어 있다. 우리는 이 행렬을 다음과 같은 규칙에 따라 적절한 크기로 자르려고 한다. 만약 종이가 모두 같은 수
www.acmicpc.net
평범한 분할정복 문제라고 생각하고 열심히 짰다.
틀린코드
N = int(input())
matrix = [list(map(int, input().split())) for _ in range(N)]
answer = [0, 0, 0] # 0, 1, -1
def check(mat):
pivot = None
for r in mat:
for c in r:
if pivot:
if pivot != c:
return False
else:
pivot = c
return True
def solve(mat, N):
# n = sqrt(n)
n = N//3
# 나눠서 재귀호출
if not check(mat):
for y in range(3):
for x in range(3):
submat = [r[n*x:n*(x+1)]
for r in mat[n*y:n*(y+1)]]
solve(submat, n)
else:
answer[mat[0][0]] += 1
solve(matrix, N)
print(answer[-1])
print(answer[0])
print(answer[1])
근데 자꾸 틀려서 짜증났다.
아무래도 인덱스를 조절하는 방법에서 문제가 있었던 것 같다.
위와 같이 리스트를 잘라서 적용하는 방법보다는
인덱스 그 자체를 전달하는 방법이 더 효율적이라고 느꼈다. (다른 코드 참조함)
정답코드
N = int(input())
matrix = [list(map(int, input().split())) for _ in range(N)]
answer = [0, 0, 0] # 0, 1, -1
def check(x, y, n):
pivot = matrix[x][y]
for i in range(x, x+n):
for j in range(y, y+n):
if pivot != matrix[i][j]:
return True
return False
def solve(x, y, n):
if check(x, y, n):
for dy in range(3):
for dx in range(3):
solve(x+dx*n//3, y+dy*n//3, n//3)
return
else:
answer[matrix[x][y]] += 1
solve(0, 0, N)
print("{}\n{}\n{}".format(answer[-1], answer[0], answer[1]))
훨씬 깔끔하고 직관적인 코드가 됐다.
'Algorithm > acmicpc.net' 카테고리의 다른 글
술 마시고도 푸는 실버3 (#11047번 동전0) (0) | 2022.03.18 |
---|---|
시간복잡도는 완벽히 알고있는 듯 한. (#11659번 구간 합 구하기 4) (0) | 2022.03.15 |
알고리즘 짤 때 가장 한심스러운 순간 (1541번 잃어버린 괄호) (0) | 2022.03.13 |
실버 쯤이야 - 그래프의 재미 (1389번 케빈 베이컨) (0) | 2022.03.13 |
분할 정복의 힘 (2630번, 1074번 파이썬) (0) | 2022.03.11 |