[백준] 2580번 - 스도쿠 (Gold 4)
업데이트:
문제 링크
문제 설명
주어진 스도쿠 문제를 풀면 된다. 문제는 반드시 풀 수 있으며, 답이 하나가 아니라면 하나만 출력해야 한다.
정답 코드 및 설명
빈 칸에 1~9를 각각 대입해보는 방식의 백트래킹이다.
주의할 점은 답이 될 수 없는 경우 대입해본 칸을 다시 0으로 돌려줘야 한다.
그대로 두게 되면 원래 문제가 변형되어 버린다.
시간을 줄이기 위해, 스도쿠 전체를 체크하지 않고 대입한 칸에 대해서만 체크를 진행하였다.
이것이 가능한 이유는 반드시 풀 수 있는 문제라는 전제가 있기 때문이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.io.*;
import java.util.*;
public class Main {
static int sudoku[][]; // 스도쿠 문제 저장
static ArrayList<Integer> blank = new ArrayList<>(); // 빈 칸의 인덱스 저장
static StringBuilder sb = new StringBuilder();
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
sudoku = new int[9][9];
for (int i = 0; i < 9; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 9; j++) {
sudoku[i][j] = Integer.parseInt(st.nextToken());
if (sudoku[i][j] == 0)
blank.add(i * 9 + j);
}
}
solve(0);
}
// 백트래킹
static void solve(int depth) throws IOException {
// 이미 답이 나온 경우 출력 후 프로그램 종료
if (depth == blank.size()) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
sb.append(sudoku[i][j]);
sb.append(" ");
}
sb.append("\n");
}
bw.write(sb.toString());
bw.close();
System.exit(0);
}
for (int i = 1; i <= 9; i++) {
if (isAble(blank.get(depth) / 9, blank.get(depth) % 9, i)) {
sudoku[blank.get(depth) / 9][blank.get(depth) % 9] = i;
solve(depth + 1);
}
}
sudoku[blank.get(depth) / 9][blank.get(depth) % 9] = 0;
}
// 특정 칸과 숫자에 대해서만 체크(나머지는 이미 만족하고 있을 것이므로)
static boolean isAble(int i, int j, int num) {
for (int k = 0; k < 9; k++) {
if (sudoku[i][k] == num)
return false;
if (sudoku[k][j] == num)
return false;
if (sudoku[3 * (i / 3) + k / 3][3 * (j / 3) + k % 3] == num)
return false;
}
return true;
}
}
댓글남기기