220v
젝무의 개발새발
220v
전체 방문자
오늘
어제
  • 분류 전체보기 (255)
    • AI (35)
      • ML, DL 학습 (30)
      • 논문 리뷰 (4)
      • 실습 및 프로젝트 (1)
    • Algorithm (145)
      • LeetCode (13)
      • 프로그래머스 (35)
      • 백준 (96)
      • 알고리즘, 문법 정리 (1)
    • Mobile, Application (17)
      • Flutter (10)
      • iOS, MacOS (7)
    • BackEnd (7)
      • Flask (1)
      • Node.js (5)
      • Spring, JSP..etc (1)
    • Web - FrontEnd (18)
      • JavaScript, JQuery, HTML, C.. (12)
      • React (6)
    • DataBase (1)
      • MySQL (1)
      • Firebase Firestore (0)
      • Supabase (0)
    • Git (1)
    • 기타 툴 및 오류 해결 (3)
    • 강의 (5)
      • Database (3)
      • 암호학 (2)
      • 알고리즘 (0)
    • 후기와 회고 (2)
    • 블로그 꾸미기 (1)
    • 일상과 이것저것 (20)
      • 맛집 (12)
      • 세상사는일 (4)
      • 도서리뷰 (1)
      • 이런저런 생각들 (잡글) (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • BFS
  • union-find
  • 위상 정렬
  • Mathematics
  • Prefix Sum
  • Greedy
  • Priority Queue
  • 구현
  • implementation
  • Minimum Spanning Tree
  • bitmasking
  • REACT
  • Dynamic Programming
  • dp
  • dfs
  • two pointer
  • topological sort
  • 프로그래머스
  • Lis
  • disjoint set
  • IMPLEMENT
  • top-down
  • brute-Force
  • binary search
  • simulation
  • 다익스트라
  • 티스토리챌린지
  • 백준
  • Backtracking
  • 오블완

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
220v

젝무의 개발새발

Algorithm/백준

[백준] 2239. 스도쿠 - 파이썬

2023. 4. 6. 13:58

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

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

 

풀이 1, 풀이 2 모두 PyPy3 기준 AC 가능(통과 가능)

 

풀이 1

Backtracking을 이용해 풀 수 있는 문제.

스도쿠를 이차원 배열에 저장하고, 0이 있는 좌표들을 리스트에 저장.

백트래킹을 이용해 모든 0이 있는 칸에 가능한 숫자를 채워준다.

recursion의 depth는 9x9 스도쿠이기 때문에 최대 81. recursion error를 걱정할 만한 깊이가 아니니 안심하고 진행.

 

처음엔 풀이 1대로 풀었다가 TLE가 나와 더 시간을 줄여야 하나? 싶어서, 풀이 2와 같이 rowCheck, colCheck 또한 boxCheck처럼 이차원 배열에 저장하는 방식으로 변경해 풀었다.

그런데 다시 보니 TLE가 나는 이유가 프로그램이 끝나지 않아서였고.. ^ㅁ^ exit() 을 넣어줌으로써 해결했다.

물론 풀이 2가 더 시간이 적게 걸리긴 하지만, 풀이 1, 풀이 2 모두 AC!

board = [list(map(int, input())) for _ in range(9)]
coors = []
'''0이 들어간 좌표 저장'''
for i in range(9):
    for j in range(9):
        if board[i][j] == 0:
            coors.append((i, j))


def rowCheck(n, row):
    if n in board[row]:
        return True
    return False


def colCheck(n, col):
    for i in range(9):
        if n == board[i][col]:
            return True
    return False


'''boxCheck[n][m-1] = n번 box에 m이 포함되었는지'''
boxCheck = [[False] * 9 for _ in range(9)]
for i in range(9):
    for j in range(9):
        if board[i][j] != 0:
            boxCheck[(i//3)*3 + j//3][board[i][j]-1] = True


def backT(n):
    '''coors(0의 좌표들) 의 개수만큼 depth가 깊어졌다면, 모든 0에 숫자를 채워넣은 상태이므로, 종료.'''
    if n == len(coors):
        for b in board:
            print(*b, sep="")
        exit()

    '''i, j = row, column'''
    i, j = coors[n]
    for k in range(1, 10):
        if rowCheck(k, i):
            continue
        if colCheck(k, j):
            continue
        if boxCheck[(i//3)*3 + j//3][k-1]:
            continue

        '''row, col, box check 후 숫자 삽입'''
        board[i][j] = k
        boxCheck[(i//3)*3 + j//3][k-1] = True

        backT(n+1)

        '''만약 더 깊은 depth에서 return이 일어났다면, backTracking을 위해 원상복구.'''
        board[i][j] = 0
        boxCheck[(i//3)*3 + j//3][k-1] = False

backT(0)

 

 

풀이 2

board = [list(map(int, input())) for _ in range(9)]
coors = []
'''0이 들어간 좌표 저장'''
for i in range(9):
    for j in range(9):
        if board[i][j] == 0:
            coors.append((i, j))


'''rowCheck[n][m-1] = n번 row에 m이 포함되었는지'''
rowCheck = [[False] * 9 for _ in range(9)]
'''colCheck[n][m-1] = n번 column에 m이 포함되었는지'''
colCheck = [[False] * 9 for _ in range(9)]
'''boxCheck[n][m-1] = n번 box에 m이 포함되었는지'''
boxCheck = [[False] * 9 for _ in range(9)]

for i in range(9):
    for j in range(9):
        if board[i][j] != 0:
            boxCheck[(i//3)*3 + j//3][board[i][j]-1] = True
            rowCheck[i][board[i][j]-1] = True
            colCheck[j][board[i][j]-1] = True


def backT(n):
    '''coors(0의 좌표들) 의 개수만큼 depth가 깊어졌다면, 모든 0에 숫자를 채워넣은 상태이므로, 종료.'''
    if n == len(coors):
        for b in board:
            print(*b, sep="")
        exit()

    '''i, j = row, column'''
    i, j = coors[n]
    for k in range(1, 10):
        if rowCheck[i][k-1]:
            continue
        if colCheck[j][k-1]:
            continue
        if boxCheck[(i//3)*3 + j//3][k-1]:
            continue

        '''row, col, box check 후 숫자 삽입'''
        board[i][j] = k
        boxCheck[(i//3)*3 + j//3][k-1] = True
        rowCheck[i][k-1] = True
        colCheck[j][k-1] = True

        backT(n+1)

        '''만약 더 깊은 depth에서 return이 일어났다면, backTracking을 위해 원상복구.'''
        board[i][j] = 0
        boxCheck[(i//3)*3 + j//3][k-1] = False
        rowCheck[i][k-1] = False
        colCheck[j][k-1] = False

backT(0)

 

    'Algorithm/백준' 카테고리의 다른 글
    • [백준] 27939. 가지 교배 - 파이썬
    • [백준] 2056. 작업 - 파이썬
    • [백준] 1806. 부분합 - 파이썬
    • [백준] 1202. 보석 도둑 - 파이썬
    220v
    220v
    DGU CSE 20 / Apple Developer Academy @ POSTECH 2nd Jr.Learner.

    티스토리툴바