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

입력
출력
[아이디어]
스도쿠에 빈칸들을 따로 저장해주었고, 행, 열, 사각형에 같은 숫자가 있는지 빠르게 체크해주기 위해서 배열을 따로 생성해주었다.
static boolean [][] row = new boolean [9][10];
static boolean [][] col = new boolean [9][10];
static boolean [][] square = new boolean [9][10];
row[i][j] = true -> i번째 행에 숫자 j가 존재한다.
square는 3 x 3 크기의 정사각형을 뜻하고, 순서는 다음과 같다.
(r, c) 위치가 어느 사각형에 속하는지 계산하는 방법은 r / 3 * 3 + c / 3 이다.
예를 들어 (4, 2) 는 4 / 3 * 3 + 2 / 0 = 3 + 0 = 3 이므로 4번째 사각형에 존재한다.
그 이후에는 백트래킹을 사용하여 가능한 경우만 탐색해주었다.
[JAVA 코드]
import java.io.*;
import java.util.*;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static StringBuilder output = new StringBuilder();
static StringTokenizer tokens;
static int [][] sudoku = new int [9][9];
static int [][] result = new int [9][9];
static boolean [][] row = new boolean [9][10];
static boolean [][] col = new boolean [9][10];
static boolean [][] square = new boolean [9][10];
static List<Point> zeros = new ArrayList<>();
static boolean flag = false;
static class Point {
int r, c;
public Point(int r, int c) {
this.r = r;
this.c = c;
}
}
public static void main(String[] args) throws IOException {
for(int r = 0; r < 9; r++) {
tokens = new StringTokenizer(br.readLine());
for(int c = 0; c < 9; c++) {
sudoku[r][c] = Integer.parseInt(tokens.nextToken());
if(sudoku[r][c] == 0) {
zeros.add(new Point(r, c));
} else {
int num = sudoku[r][c];
row[r][num] = true;
col[c][num] = true;
square[r / 3 * 3 + c / 3][num] = true;
}
}
}
solution(0);
for(int r = 0; r < 9; r++) {
for(int c = 0; c < 9; c++) {
output.append(result[r][c] + " ");
}
output.append("\n");
}
System.out.println(output);
}
private static void solution(int cnt) {
if(flag) return; // 이미 답을 찾은 경우
if(cnt == zeros.size()) {
flag = true;
copyResult();
return;
}
for(int i = 1; i <= 9; i++) {
int r = zeros.get(cnt).r;
int c = zeros.get(cnt).c;
// 이미 행 또는 열 또는 사각형에 같은 숫자가 있는 경우
if(row[r][i] || col[c][i] || square[r/3*3 + c/3][i]) continue;
// 현재 빈칸에 숫자 채워주기
sudoku[r][c] = i;
row[r][i] = true;
col[c][i] = true;
square[r / 3 * 3 + c / 3][i] = true;
solution(cnt + 1);
// 빈칸에 숫자 지워주기
sudoku[r][c] = 0;
row[r][i] = false;
col[c][i] = false;
square[r / 3 * 3 + c / 3][i] = false;
}
}
// 결과 따로 저장하기
private static void copyResult() {
for(int r = 0; r < 9; r++) {
for(int c = 0; c < 9; c++) {
result[r][c] = sudoku[r][c];
}
}
}
}
'알고리즘 > BAEKJOON' 카테고리의 다른 글
[백준] 13265 색칠하기 (Java) (0) | 2022.05.29 |
---|---|
[백준] 11653 소인수분해 (Java) (0) | 2022.05.26 |
[백준] 11509 풍선 맞추기 (Java) (0) | 2022.05.20 |
[백준] 15681 트리와 쿼리 (Java) (0) | 2022.05.20 |
[백준] 17141 연구소2 (Java) (0) | 2022.05.20 |
댓글