알고리즘/백준
백준 2239 스도쿠 Java [백트래킹, DFS]
쫑쫑2
2022. 11. 13. 04:42
https://www.acmicpc.net/problem/2239
2239번: 스도쿠
스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다
www.acmicpc.net
각 행과 열, 3x3 사각형의 방문 배열을 만들어 1 ~ 9 까지 중복없이 스도쿠 퍼즐을 채운다
3x3 사각형의 방문 배열의 경우 왼쪽 위에서부터 순서대로 배정했고,
행을 3으로 나눈 몫에 3을 곱하고, 열을 3으로 나눈 몫을 더해주면 해당 인덱스에 접근할 수 있다
사전식에서 가장 앞서는 경우를 출력해야하기 때문에 각 자리를 1부터 9까지 가능한 경우의 수를 구하고
끝까지 구해질 경우 탈출조건을 줘서 탐색을 멈추게 했다
import java.io.*;
import java.util.*;
public class Main {
static int[][] puzzle;
static boolean[][] row_vtd, col_vtd, squ_vtd;
static boolean isFind;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
puzzle = new int[9][9];
row_vtd = new boolean[9][10];
col_vtd = new boolean[9][10];
squ_vtd = new boolean[9][10];
isFind = false;
for (int i = 0; i < 9; i++) {
puzzle[i] = Arrays.stream(br.readLine().split("")).mapToInt(Integer::parseInt).toArray();
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (puzzle[i][j] != 0) {
setVtd(i, j, puzzle[i][j], true);
}
}
}
dfs(0, 0);
for (int[] p : puzzle) {
Arrays.stream(p).forEach(sb::append);
sb.append("\n");
}
sb.setLength(sb.length() - 1);
System.out.println(sb);
}
static void dfs(int r, int c) {
if (r == 8 && c == 9) {
isFind = true;
return;
}
if (c == 9) {
r++;
c %= 9;
}
if (puzzle[r][c] != 0) dfs(r, c + 1);
else {
for (int n = 1; n < 10; n++) {
if (!isVtd(r, c, n)) {
setVtd(r, c, n,true);
dfs(r, c + 1);
if (isFind) {break;}
setVtd(r, c, n, false);
};
}
}
}
static void setVtd(int r, int c, int n, boolean tf) {
row_vtd[r][n] = tf;
col_vtd[c][n] = tf;
squ_vtd[(r/3)*3 + c/3][n] = tf;
puzzle[r][c] = tf ? n : 0;
}
static boolean isVtd(int r, int c, int n) {
return row_vtd[r][n] || col_vtd[c][n] || squ_vtd[(r/3)*3 + c/3][n];
}
}
어디가 틀린지 모르고 dfs 메서드를 전체 디버깅하니까 틀린 지점 찾는데 너무 오래걸렸다
디버깅 포인트를 설정할 때 어디에 설정할지 좀 더 생각해봐야겠다