ABOUT ME

Today
-
Yesterday
-
Total
-
  • 2580. 스도쿠
    Algorithm/Baekjoon 2023. 3. 20. 00:15

    문제가 길다...

     

    백트래킹 방식으로 풀 수 있다. N-queen문제의 접근 방법과 비슷한데, 가로, 세로, 3x3 박스 각각 체크할 수 있도록 체크 배열을 만들면 된다.

    1. 가로를 체크하는 check_row 배열의 경우 몇번째 줄에 어떤 숫자가 들어갔는지를 체크하도록 해야 한다.

    즉, check_row[3][2] = True 라면, 네번째 줄 (첫번째 줄은 0번 index니까)에 2라는 숫자가 존재한다는 것.

    2. 세로를 체크하는 check_col 배열도 동일하다.

    3. 3x3 박스를 체크하는 check_box 배열의 경우 몇번째 box에 어떤 숫자가 들어갔는지를 체크해야 한다.

    몇번째 박스인지를 어떻게 알까? \

    3개씩 끊어주면 되니까 3으로 나눈 값을 잘 사용하면 나타낼 수 있을 것 같다.

    난 각 box를 (i//3)*2+j//3으로 표현하여 사용하였다. 이러면 3x3 박스를 각각 0부터 8번 index까지 나타낼 수 있다. (한 번 직접 계산해보면 알 수 있다.)

     

    이제 입력값을 받은 스도쿠 판을 확인하여 체크 배열들을 채워주어야 한다.

    체크 배열들을 잘 채워주었다면 각 가로세로박스에 대하여 False인 값들이 우리가 채워주어야 하는 값들이 될 것이다.

     

    이후는 백트래킹 방식을 잘 사용해주면 된다. cnt를 증가시키면서 가로세로 좌표값을 얻어주고 각 칸에 대해 칸의 값이 0이라면 비어있는 칸이므로 1부터 숫자를 넣어주면서 만족하는지 확인해준다. 코드를 뜯어보면 훨씬 이해하기 쉬울 것이다.

     

    # 스도쿠
    # 가로줄과 세로줄에는 1부터 9까지의 숫자가 한번씩만 나타나야 함
    # 굵은 선으로 구분되어 있는 정사각형 안에도 1부터 9까지의 숫자가 한 번씩만 나타나야 함
    import sys
    input = sys.stdin.readline
    
    ROW = 9
    check_row = [[False] * 10 for _ in range(10)] 
    check_col = [[False] * 10 for _ in range(10)] 
    check_box = [[False] * 10 for _ in range(10)] 
    
    def pre_check() :
        for i in range(9) :
            for j in range(9) :
                if board[i][j] == 0 :
                    continue
                check_row[i][board[i][j]] = True
                check_col[j][board[i][j]] = True
                check_box[(i//3)*3+(j//3)][board[i][j]] = True
    
    def make_sudoku(cnt) :
        if cnt == ROW*ROW :
            return True
        x = cnt//9
        y = cnt%9
        if board[x][y] > 0 :
            return make_sudoku(cnt+1)
        for i in range(1, 10) :
            if check_row[x][i] or check_col[y][i] or check_box[(x//3)*3+(y//3)][i] :
                continue
            board[x][y] = i
            check_row[x][i] = True
            check_col[y][i] = True
            check_box[(x//3)*3+(y//3)][i] = True
            if make_sudoku(cnt+1) :
                return True
            board[x][y] = 0
            check_row[x][i] = False
            check_col[y][i] = False
            check_box[(x//3)*3+(y//3)][i] = False
        return False
    
    board = [list(map(int, input().split())) for _ in range(9)]
    
    pre_check()
    make_sudoku(0)
    
    for line in board : 
        print(*line)

    'Algorithm > Baekjoon' 카테고리의 다른 글

    10971. 외판원 순회  (0) 2023.03.19
    9663. N-queen  (0) 2023.03.06
    1205. 등수 구하기  (0) 2023.03.06
    1009. 분산처리  (0) 2023.03.01
    11723. 집합  (0) 2023.02.27

    댓글

Designed by nanometre380.