코딩테스트/백준

[백준] 2580번: 스도쿠

yjseo01 2023. 9. 20. 13:26

https://www.acmicpc.net/problem/2580

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루

www.acmicpc.net

 

처음에는 이렇게 풀었었는데, 문제에 제시된 테스트 케이스만 통과했어서, 

결국 풀이를 찾아봤다.

 

import sys
from collections import deque
input = sys.stdin.readline

def backtracking(y, x): # 좌표
    if matrix[y][x] != 0:
        return

    for i in range(1, 10):
        endflag = True

        # 가로줄, 세로줄 검사
        for j in range(9):
            if matrix[y][j] == 0:
                queue.append((y, j))
            if matrix[j][x] == 0:
                queue.append((j, x))

            if matrix[y][j] == i or matrix[j][x] == i:
                endflag = False
                break

        # 3x3 정사각형 검사
        for row in range((x // 3) * 3, (x // 3) * 3 + 3):
            for col in range((y // 3) * 3, (y // 3) * 3 + 3):
                if matrix[col][row] == 0:
                    queue.append((col, row))

                if matrix[col][row] == i:
                    endflag = False
                    break

        if endflag:
            matrix[y][x] = i
        else:
            continue

    if queue:
        ny, nx = queue.popleft()
        backtracking(ny, nx)
    else: # 더이상 빈칸이 없음
        return

queue = deque() # 빈 칸의 좌표를 저장할 queue
matrix = [list(map(int, input().split())) for _ in range(9)]

for i in range(9):
    for j in range(9):
        if matrix[i][j] == 0:
            backtracking(i, j)

# 답 출력
for i in range(9):
    for j in range(9):
        print(matrix[j][i], end=" ")
    print()

처음에는 deque 자료구조에 빈 칸을 모두 넣고 하나씩 pop해서 풀려고 했는데, 

그렇게 하면 해당 숫자가 그 자리에 올바르지 못한 숫자일 경우 다시 초기화하는 코드가 없어서 

제대로 답을 도출해 낼 수 없는 것이 아닐까?

 

backtracking함수를 재귀 호출 후 왜 스도쿠 판을 초기화시켜야 하는지 이해가 안갔었는데,

좀 더 생각해보니까 backtraking함수 호출 밑의 코드는 답을 찾지 못한 경우에만 실행이 되는 것이므로

다른 숫자를 넣어볼 수 있게 0으로의 초기화가 필요한 것 같다.

 

답을 찾았을 경우 return 문이 아닌 exit()문을 써야 하는 이유도 궁금했는데,

직접 return문으로 바꿔보니까 return문으로 빠져나가면 backtraking 함수를 호출하고 나서의 코드가 실행되어 무한루프에 빠질 수 있기 때문이었다.

이걸 직접 해봐서 깨닫다니 솔직히 좀 바보같았던거같다ㅋㅋㅋ😂

 

 

참고
2580번 풀이: https://edder773.tistory.com/255

'코딩테스트 > 백준' 카테고리의 다른 글

[백준] 1987번: 알파벳  (0) 2023.09.22
[백준] 6603번: 로또  (0) 2023.09.21
[백준] 1759번: 암호 만들기  (0) 2023.09.19
[백준] 5014번: 스타트링크  (0) 2023.09.18
[백준] 2186번: 문자판  (0) 2023.09.17