문제풀이/백준

백준 2580 스도쿠 문제풀이

soo-dal 2024. 1. 5. 13:47

문제 

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

 

2580번: 스도쿠

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

www.acmicpc.net

 

 

 

 

문제 접근 방식

빈칸을 하나씩 순회하면서 숫자를 채워넣는 방식으로 구현을 했다.

숫자를 채워넣는 경우 1~9를 모두 채워넣는 방식이 아닌 현재 행, 열을 통해서 해당 행의 가능한 숫자, 해당 열에서 가능한 숫자 , 해당 그룹에서 가능한 숫자의 교집합을 통해서 가능한 숫자를 추렸다. 이후 가능한 숫자를 하나씩 넣고 다음 빈칸으로 넘어가는 방식으로 스도쿠를 풀었다.

 

 

코드

def cal_group(row,col):
    y=row//3
    x=col//3
    return 3*y+x

def dfs(index):
    if index== len(empty):
        # 모두 채워졌다면 출력
        for i in range(9):
            for j in range(9):
                print(board[i][j],end=' ')
            print()
        return True

    r,c=empty[index]
    group_num=cal_group(r,c)
    possible_nums=rows[r] & cols[c] & groups[group_num]

    for num in list(possible_nums):
        rows[r].remove(num)
        cols[c].remove(num)
        groups[group_num].remove(num)
        board[r][c]=num

        # 출력이 되었다면 True를 반환
        if dfs(index+1):
            return True

        #원상복구
        rows[r].add(num)
        cols[c].add(num)
        groups[group_num].add(num)
        board[r][c]=0

    return False

if __name__=='__main__':
    global board,empty,rows,cols,groups
    board=[]
    for _ in range(9):
        board.append(list(map(int,input().split())))

    empty=[]
    rows = [set([i for i in range(1,10)]) for _ in range(9)]
    cols = [set([i for i in range(1,10)]) for _ in range(9)]
    groups = [set([i for i in range(1,10)]) for _ in range(9)]

    # 빈칸의 위치 정보를 리스트에 저장
    for i in range(9):
        for j in range(9):
            if board[i][j]==0:
                empty.append((i,j))
            else:
                rows[i].remove(board[i][j])
                cols[j].remove(board[i][j])
                group_num=cal_group(i,j)
                groups[group_num].remove(board[i][j])

    dfs(0)

 

 

회고

 

파이썬에서 시간초과가 나서 pypy3 로 돌려서 코드가 맞는지만 확인해보았다.

상위 파이썬 문제 풀이를 보니 100ms 인거 보면 접근 방식을 다르게 해야되는 것 같다. 

다른 문제풀이는 어떻게 되어 있는지 확인하고 수정을 하겠다.