본문 바로가기
알고리즘/백준

[백준 2580] 스도쿠

by RoJae 2019. 5. 8.


스도쿠 문제이다.

주어진 스도쿠를 3가지 조건을 만족하여

다양한 경우의 수 중에서 하나만 출력하면 된다.


조건1 : 각각의 가로 줄에는 1 ~ 9 숫자 하나씩만 가능하다.

조건2 : 각각의 세로 줄에는 1 ~ 9 숫자 하나씩만 가능하다.

조건3 : 작은 3*3 사각형에는 1 ~ 9 숫자 하나씩만 가능하다.


나의 경우에는 bool check1, 2, 3을 사용하여 구현하였으며

int sudoku[9][9];                    // 기존의 스도쿠 배열
vector<pair<intint> > list;        // 비어있는 스도쿠 배열


list의 x와 y를 활용하여, 1부터 9까지 순회시켜

조건 1,2,3에 부합할 경우 다음 깊이로 진행한다. (DFS 탐색)


모든 깊이를 탐색할 시

다양한 경우의 수가 나오기 때문에

(문제에서 제시한 답은 경우의 수 1개)

강제로 종료시킨다.


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

나머지 빈 칸을 채우는 방식은 다음과 같다.

  1. 각각의 가로줄과 세로줄에는 1부터 9까지의 숫자가 한 번씩만 나타나야 한다.
  2. 굵은 선으로 구분되어 있는 3x3 정사각형 안에도 1부터 9까지의 숫자가 한 번씩만 나타나야 한다.

위의 예의 경우, 첫째 줄에는 1을 제외한 나머지 2부터 9까지의 숫자들이 이미 나타나 있으므로 첫째 줄 빈칸에는 1이 들어가야 한다.

또한 위쪽 가운데 위치한 3x3 정사각형의 경우에는 3을 제외한 나머지 숫자들이 이미 쓰여있으므로 가운데 빈 칸에는 3이 들어가야 한다.

이와 같이 빈 칸을 차례로 채워 가면 다음과 같은 최종 결과를 얻을 수 있다.

게임 시작 전 스도쿠 판에 쓰여 있는 숫자들의 정보가 주어질 때 모든 빈 칸이 채워진 최종 모습을 출력하는 프로그램을 작성하시오.

입력

아홉 줄에 걸쳐 한 줄에 9개씩 게임 시작 전 스도쿠판 각 줄에 쓰여 있는 숫자가 한 칸씩 띄워서 차례로 주어진다. 스도쿠 판의 빈 칸의 경우에는 0이 주어진다. 스도쿠 판을 규칙대로 채울 수 없는 경우의 입력은 주어지지 않는다.

출력

모든 빈 칸이 채워진 스도쿠 판의 최종 모습을 아홉줄에 걸쳐 한 줄에 9개씩 한 칸씩 띄워서 출력한다.

스도쿠 판을 채우는 방법이 여럿인 경우는 그 중 하나만을 출력한다.

예제 입력 1

0 3 5 4 6 9 2 7 8
7 8 2 1 0 5 6 0 9
0 6 0 2 7 8 1 3 5
3 2 1 0 4 6 8 9 7
8 0 4 9 1 3 5 0 6
5 9 6 8 2 0 4 1 3
9 1 7 6 5 2 0 8 0
6 0 3 7 0 1 9 5 2
2 5 8 3 9 4 7 6 0

예제 출력 1

1 3 5 4 6 9 2 7 8
7 8 2 1 3 5 6 4 9
4 6 9 2 7 8 1 3 5
3 2 1 5 4 6 8 9 7
8 7 4 9 1 3 5 2 6
5 9 6 8 2 7 4 1 3
9 1 7 6 5 2 3 8 4
6 4 3 7 8 1 9 5 2
2 5 8 3 9 4 7 6 1




소스코드

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
#include<iostream>
#include<vector>
#include<utility>
 
using namespace std;
 
int sudoku[9][9];
vector<pair<intint> > list;
 
// sudoku 배열에 삽입
// 비어있는 스도쿠 배열은 vector list에 삽입 
void insert(){
    for(int i = 0; i < 9; i++){
        for(int j = 0; j < 9; j++){
            int tmp;
            cin >> tmp;
            sudoku[i][j] = tmp;
            if(tmp == 0)
                list.push_back(make_pair(i,j));
        }
    }
}
 
// 가로 검사  
bool check1(int r, int num){
    for(int i = 0; i < 9; i++){
        if(sudoku[r][i] == num)
            return false;
    }
    return true;
}
 
// 세로 검사  
bool check2(int c, int num){
    for(int i = 0; i < 9; i++){
        if(sudoku[i][c] == num)
            return false;
    }
    return true;
}
 
// 3x3 검사  
bool check3(int r, int c, int num){
    r = r / 3;
    c = c / 3;
    for(int rr = r * 3; rr < (r * 3+ 3;  rr++){
        for(int cc = c * 3; cc < (c * 3+ 3; cc++){
            if(sudoku[rr][cc] == num)
                return false;
        }
    }
    return true;
}
bool pass(int x, int y, int num){
    return (check1(x,num) && check2(y,num) && check3(x,y,num))? true : false;
}
 
// dfs 탐색을 사용하여 비어있는 스도쿠 공간을 채운다.
void dfs(int index){
    if(index == list.size()){                                    // 이미 비어있는 모든 공간을 채운 상태 
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < 9; j++)
                cout << sudoku[i][j] << ' ';
            cout << '\n';
        }
        exit(0);                                                // 강제 종료 
    }
    
    for(int i = 1; i <= 9; i++){                                // 1부터 9까지 삽입해본다. 
        int x = list[index].first;                                // 가로 
        int y = list[index].second;                                // 세로  
        if(pass(x,y,i)){        // 스도쿠 조건에 만족하면  
            sudoku[x][y] = i;                                    // sudoku 배열에 삽입     
            dfs(index+1);                                        // 비어있는 다음 스도쿠 배열을 탐색 
            sudoku[x][y] = 0;                                    // 위에서 스도쿠 조건 만족에 실패하여 다시 빠져나옴 
        }
    }
}
int main(void){
    insert();                                                    // 기존의 스도쿠 배열 삽입 
    dfs(0);                                                        // dfs 탐색 
    return 0;
}
cs


※ 본 글은 개인 포트폴리오 혹은 공부용으로 사용하기 때문에, 무단 복사 유포는 금지하지만, 개인 공부 용도로는 얼마든지 사용하셔도 좋습니다.


'알고리즘 > 백준' 카테고리의 다른 글

[백준 1182] 부분수열의 합  (0) 2019.05.11
[백준 1987] 알파벳  (0) 2019.05.11
[백준 9663] N-Queen  (0) 2019.05.08
[백준 1759] 암호 만들기  (0) 2019.04.28

댓글