본문 바로가기

브루트 포스/브루트포스(재귀)

스도쿠 (백트래킹)

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

 

2580번: 스도쿠

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

www.acmicpc.net

백 트래킹으로 칸에 들어가지 못하는 수는 아예 넣지를 말자

n-queen 문제와 유사. 행, 열, 정사각형을 검사해야한다

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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
 
using namespace std;
 
int sudo[10][10];
bool c[10][10];  // 행 9개
bool c2[10][10]; // 열 9개
bool c3[10][10]; // 정사각형 9개
 
// 정사각형 번호 매기기
int square(int x, int y)
{
    return (x / 3* 3 + (y / 3);
}
 
bool go(int z)
{
    //출력
    if (z == 81
    {
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                cout << sudo[i][j] << ' ';
            }
            cout << '\n';
        }
        return true;
    }
    
    // 이차원 배열에 번호 붙이기
    // k / m -> 행    k % m -> 열
    int x = z / 9;
    int y = z % 9;
    
    // 백트래킹
    if (sudo[x][y] != 0)
    {
        return go(z + 1);
    }
    else  // 0 일 때 
    {
        for (int i = 1; i <= 9; i++)
        {
            if (c[x][i] == 0 && c2[y][i] == 0 && c3[square(x, y)][i] == 0)
            {
                c[x][i] = c2[y][i] = c3[square(x, y)][i] = true;
                sudo[x][y] = i;
                if (go(z + 1))  
                    return true;
                //브루트포스니까 다시 바꿔줘야함
                sudo[x][y] = 0;
                c[x][i] = c2[y][i] = c3[square(x, y)][i] = false;
 
            }
        }
    }
    return false;
}
 
int main()
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            scanf("%d"&sudo[i][j]);
            
            if (sudo[i][j] != 0)
            {
                c[i][sudo[i][j]] = true;
                c2[j][sudo[i][j]] = true;
                c3[square(i, j)][sudo[i][j]] = true;
            }
        }
    }
 
    go(0);
    return 0;
}
cs

 if (go(z + 1)) 

    return true;
 
for문을 다 돌았는데도 숫자가 없다면 false가 반환될 것이고
돌아가서 그 값을 끈다.
 
z == 81이 되면 이제 모든 칸을 다 채운 것
돌아가면서 다 return true를 시켜야 하므로!!!

'브루트 포스 > 브루트포스(재귀)' 카테고리의 다른 글

에너지 모으기  (0) 2023.05.29
두 동전  (0) 2023.05.10
좋은 수열  (0) 2023.04.09
신기한 소수  (0) 2023.04.04
N-Queen (중요!)  (0) 2023.04.01