본문 바로가기
Algorithms

백준 2580. 스도쿠

by Brian Go 2022. 6. 20.

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

 

2580번: 스도쿠

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

www.acmicpc.net

괴랄해 보여서 쫄리지만 생각보다는, '생각보다는' 쉬운 문제. 그래도 아직 어렵긴 하다.

 

기본적인 dfs에서 N-Queens와 다르게 꼼짝없이 이중 리스트를 사용해야 하는데, 이에 따라 검사하는 방법도 가로, 세로, 스도쿠의 3*3 작은 사각형을 검사해줘야 한다. 개인적으로 사각형 검사 부분이 가장 까다로웠던 것 같다.

 

기본적인 아이디어는 다음과 같다.

1. 기존 dfs와는 조금 다르게, 빈 공간이 아무렇게나 주어지지 않으므로 이에 대한 정보가 필요하다.

2. 빈 공간의 x, y를 가지고 검사 메서드를 짜야 한다.

 

빈 공간은 0으로 주어지기에 배열을 받고 나서 반복문을 통해 빈 공간의 좌표를 모두 담아주고, 이를 통해 dfs를 진행했다.

 

sudoku = []
blanks = []
for i in range(9): #스도쿠 맵 초기화
	sudoku.append(list(map(int, input().split())))

for i in range(9):
	for j in range(9):
		if sudoku[i][j] == 0: #빈칸 인덱스 값 받기
			blanks.append([i, j])
def check_row(x, num): # 세로 검사
	for i in range(9):
		if num == sudoku[x][i]:
			return False
	return True

def check_col(y, num): # 가로 검사
	for i in range(9):
		if num == sudoku[i][y]:
			return False
	return True

def check_rectangle(x, y, num): # 3x3 사각형 검사
	x = x//3 * 3 #제일 왼쪽 위 x값 찾기
	y = y//3 * 3 #제일 왼쪽 위 y값 찾기
	for i in range(3): # 3x3 검사
		for j in range(3):
			if sudoku[x + i][y + j] == num:
				return False
	return True
	
def dfs(blank_idx):
	if len(blanks) == blank_idx:
		for i in range(9):
			for j in range(9):
				print(sudoku[i][j], end= " ")
			print()
		exit()
	x = blanks[blank_idx][0]
	y = blanks[blank_idx][1]
	for i in range(1, 10):
		if check_row(x, i) and check_col(y, i) and check_rectangle(x, y, i):
			sudoku[x][y] = i
			dfs(blank_idx + 1)
			sudoku[x][y] = 0 #탈락이면 원활한 검사를 위해 값 초기화

dfs(0)

'Algorithms' 카테고리의 다른 글

백준 14889. 스타트와 링크  (0) 2022.06.21
백준 14888. 연산자 끼워넣기  (0) 2022.06.20
백준 9663. N-Queen  (0) 2022.06.20
백준 15651. N과 M(3)  (0) 2022.06.17
백준 15649. N과 M (1)  (0) 2022.06.16

댓글