Problem Solving/Else

BOJ 2239 : 스도쿠

PS리버싱마크해커박종휘TV 2022. 3. 27. 14:56

3줄요약

  • 백트래킹
  • 빡구현

 

서론

 

이 문제를 보고 처음에 난감했었다. 이 문제가 어떻게 골드 4인지 모를 만큼 감이 안 잡혔다. 이 문제를 브루트포스로 풀면 최대 O(9^81) 의 시간복잡도가 나오기 때문에, 이 문제는 브루트 포스로 풀 수 없다. 하지만, 백트래킹을 잘 하면 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 ...  
                 
                 
                 
                 
                 
                 

다음의 순서대로 진행하되, 그 자리에 숫자를 넣었을 때 안되는 경우를 미리 체크해 주면서 백트래킹을 실행하면, 문제가 풀린다. 코드는 밑에 있다.

 

 

#include <iostream>
#include <string>

using namespace std;

int sudoku[9][9];
int d[9][2][2] = { { {0, 3}, {0, 3} }, { {3, 6}, {0, 3} }, { {6, 9} , {0, 3} }, 
{ {0, 3}, {3, 6} }, { {3, 6}, {3, 6} }, { {6, 9} , {3, 6} }, 
{ {0, 3}, {6, 9} }, { {3, 6}, {6, 9} }, { {6, 9} , {6, 9} } };
int g[9] = { 0, 0, 0, 1, 1, 1, 2, 2, 2 };
bool ended = false;


void solve(int x, int y, int num, int nowsudoku[9][9]) {
    
    if (ended) return;

    for (int i = 0; i < 9; i++) {
        if (nowsudoku[i][y] == num) return;
        if (nowsudoku[x][i] == num) return;
    }

    int op = g[y] * 3 + g[x];
    int fromx = d[op][0][0]; int tox = d[op][0][1]; int fromy = d[op][1][0]; int toy = d[op][1][1];
    for (int i = fromx; i < tox; i++) {
        for (int j = fromy; j < toy; j++) {
            if (nowsudoku[i][j] == num) return;
        }
    }

    int newsudoku[9][9];
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            newsudoku[i][j] = nowsudoku[i][j];
        }
    }
    newsudoku[x][y] = num;

    int nxt[2] = { -1, -1 }; int cnt = 0;
    for (int i = 0; i < 9; i++) {
        bool endloop = false;
        for (int j = 0; j < 9; j++) {
            if (newsudoku[i][j] == 0) {
                nxt[0] = i; nxt[1] = j; endloop = true; break;
            }
        }
        if (endloop) break;
    }

    if (nxt[0] == -1 || nxt[1] == -1) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                sudoku[i][j] = newsudoku[i][j];
            }
        }
        ended = true;
        return;
    }

    for (int i = 1; i <= 9; i++) {
        solve(nxt[0], nxt[1], i, newsudoku);
    }
    return;
}

int main() {

    for (int i = 0; i < 9; i++) {
        string s; cin >> s;
        for (int j = 0; j < 9; j++) {
            sudoku[i][j] = s[j] - 48;
        }
    }

    int initialize[2];
    for (int i = 0; i < 9; i++) {
        bool endloop = false;
        for (int j = 0; j < 9; j++) {
            if (sudoku[i][j] == 0) {
                initialize[0] = i; initialize[1] = j; endloop = true; break;
            }
        }
        if (endloop) break;
    }

    for (int i = 1; i <= 9; i++) solve(initialize[0], initialize[1], i, sudoku);

    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) { if (sudoku[i][j] == 0) { printf("IMPOSSIBLE\n"); return 0; } printf("%d", sudoku[i][j]); }
        printf("\n");
    }
}

 

 

결론

 

구현 연습도 했고, 실용성이 전혀 없는 다른 백준 문제와는 달리 이 문제는 내 책장에 있는 스도쿠 문제집을 풀 수 있기에 유용하게 사용할 수 있다.

 

난이도(개인적): Gold III

난이도(객관적): Gold IV

 

Contact: How2Contact (tistory.com)

'Problem Solving > Else' 카테고리의 다른 글

BOJ 1826 : 연료 채우기  (0) 2022.03.28
BOJ 2887 : 행성 터널  (0) 2022.03.27
BOJ 13308 : 주유소  (0) 2022.03.26
BOJ 1987 : 알파벳  (0) 2022.03.23
BOJ 2623 : 음악프로그램  (0) 2022.03.23