Competition/Baekjoon

[백준] 2580번 자바 스도쿠

bisi 2020. 5. 10. 13:56
문제 출처 

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

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루어진 정사각형 판 위에서 이뤄지는데, 게임 시작 전 몇 몇 칸에는 1부터 9까지의 숫자 중 하나가 쓰여 있다. 나머지 빈 칸을 채우는 방식은 다음과 같다. 각각의 가로줄과 세로줄에는 1부터 9까지의 숫자가 한 번씩만 나타나야 한다. 굵은 선으로 구분되어 있는 3

www.acmicpc.net

 

 

접근 방식 및 풀이

- 백트래킹 + DFS 문제

- N-Queen (백준 9663번)과 비슷한 문제

- 백트래킹 3가지 조건 : 가로 중복 체크, 세로 중복 체크, 3x3 중복체크 

- DFS  : 체크 메소드를 거치며 유망한 노드들을 DFS로 재귀호출한다.

- 참고블로그

 

 

소스 코드 
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import java.util.ArrayList;
import java.util.Scanner;
 
 
class xy{
    int x ;
    int y ;
 
    public xy(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
 
public class Main {
 
    static int[][] check ;
 
    static ArrayList<xy> arrayList = new ArrayList<xy>();
    public static void main(String[] args) {
 
        Scanner sc = new Scanner(System.in);
        check = new int[9][9];
        for (int i = 0; i <9 ; i++) {
            for (int j = 0; j <9 ; j++) {
                check[i][j] = sc.nextInt();
            }
        }
 
        for (int i = 0; i < 9 ; i++) {
            for (int j = 0; j <9 ; j++) {
                if(check[i][j] == 0){
                    arrayList.add(new xy(i,j)); // 배열의 xy 정보를 list에 저장
                }
            }
        }
        dfs (arrayList,0);
    }
 
    static private void dfs(ArrayList<xy> arr, int idx){
 
        if(idx == arrayList.size()) {// 다찾았으면 출력함.
            for (int i = 0; i <9 ; i++) {
                for (int j = 0; j <9 ; j++) {
                    System.out.print(check[i][j]+ " ");
                }
                System.out.println("");
            }
            System.exit(0);
        }
 
        for (int i = 1; i <10 ; i++) { //1~9까지 숫자가 적합한지 탐색
            if(checkRow(arr,idx,i) == true && checkCol(arr,idx,i) == true && checkBox(arr,idx,i) == true){
                // 적합하면 index에 그 숫자를 넣고
                check[arr.get(idx).x][arr.get(idx).y] = i;
                // i가 9인채로 반복문이 종료되게 되면 이전에 저 숫자 탐색색                
                dfs(arr, idx+1);
            }
 
            if(i==9){ // check[][]배열 0으로 다시 셋팅
                check[arr.get(idx).x][arr.get(idx).y] = 0;
            }
        }
    }
 
    // 가로행 중복검사
    static boolean checkRow(ArrayList<xy> arr, int idx, int pro){
        for (int i = 0; i <9 ; i++) {
            if(arr.get(idx).y == i) continue//빈칸은 건너뜀
            if(check[arr.get(idx).x][i] == pro) return false;//숫자가 이미 존재하면 false
        }
        return true;
    }
 
    //세로열 중복검사
    static boolean checkCol(ArrayList<xy> arr, int idx, int pro){
        for (int i = 0; i <9 ; i++) {
            if(arr.get(idx).x == i) continue;//빈칸은 건너뜀
            if(check[i][arr.get(idx).y] == pro) return false;//숫자가 이미 존재하면 false
        }
        return true;
    }
 
    static boolean checkBox(ArrayList<xy> arr, int idx, int pro){
 
        // 시작점
       int a = arr.get(idx).x/3;
        int b = arr.get(idx).y/3;
        a *= 3;
        b *= 3;
 
        for (int i = a; i <a+3 ; i++) {
            for (int j = b; j <b+3 ; j++) {
                if(i == arr.get(idx).x && j==arr.get(idx).y) continue;
                if(check[i][j]!=0 && check[i][j] == pro) return false;
            }
        }
 
        return true;
    }
 
 
}

 

 

결과