ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준]2239: 스도쿠(java)
    Algorithm/백준 2022. 4. 9. 20:57
    728x90
     

    2239번: 스도쿠

    스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

    www.acmicpc.net

    스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다음을 보자.

    위 그림은 참 잘도 스도쿠 퍼즐을 푼 경우이다. 각 행에 1부터 9까지의 숫자가 중복 없이 나오고, 각 열에 1부터 9까지의 숫자가 중복 없이 나오고, 각 3×3짜리 사각형(9개이며, 위에서 색깔로 표시되었다)에 1부터 9까지의 숫자가 중복 없이 나오기 때문이다.

    하다 만 스도쿠 퍼즐이 주어졌을 때, 마저 끝내는 프로그램을 작성하시오.

    입력

    9개의 줄에 9개의 숫자로 보드가 입력된다. 아직 숫자가 채워지지 않은 칸에는 0이 주어진다.

    출력

    9개의 줄에 9개의 숫자로 답을 출력한다. 답이 여러 개 있다면 그 중 사전식으로 앞서는 것을 출력한다. 즉, 81자리의 수가 제일 작은 경우를 출력한다.

    제한

    • 12095번 문제에 있는 소스로 풀 수 있는 입력만 주어진다.
      • C++17: 180ms
      • Java 15: 528ms
      • PyPy3: 2064ms

    예제 입력 1 

    103000509
    002109400
    000704000
    300502006
    060000050
    700803004
    000401000
    009205800
    804000107
    

    예제 출력 1 

    143628579
    572139468
    986754231
    391542786
    468917352
    725863914
    237481695
    619275843
    854396127

    풀이

    중복 순열을 이용한 백트래킹 문제였습니다.

    중복 순열을 주는것 처럼 1부터 빈칸에 넣어 넣을 수 있는 모든 경우의 수를 비교해보며 맞는 경우를 도출합니다.

    사전순이여야 하므로 순열은 반드시 1부터 확인해줍니다.

    1. 0인 좌표를 찾습니다.

    private static int[] findZeroIdx() {
        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                if(map[i][j] == 0) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[]{-1, -1};
    }

    2. 만약 0인 좌표가 없다면 스도쿠를 완성한 것 입니다.

    if(idx[0] == -1) {
        printSdoku();
        System.exit(0);
    }

    3. 1부터 0인 좌표에 넣어봅니다.

    for(int i=1; i<=9; i++) {
        if(isValidPosition(idx, i)) {
            map[idx[0]][idx[1]] = i;
            playSdoku();
            map[idx[0]][idx[1]] = 0;
        }
    }

    전체코드

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class BJ_G4_2239_스도쿠 {
        static final int N = 9;
        static int[][] map;
        public static void main(String[] args) throws Exception{
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            map = new int[N][N];
    
            //입력
            for(int i=0; i<N; i++) {
                String str = br.readLine();
                for(int j=0; j<N; j++) {
                    map[i][j] = str.charAt(j)-'0';
                }
            }
    
            playSdoku();
        }
    
        private static void playSdoku() {
            int[] idx = findZeroIdx();
    
            if(idx[0] == -1) {
                printSdoku();
                System.exit(0);
            }
    
            for(int i=1; i<=9; i++) {
                if(isValidPosition(idx, i)) {
                    map[idx[0]][idx[1]] = i;
                    playSdoku();
                    map[idx[0]][idx[1]] = 0;
                }
            }
        }
    
        private static int[] findZeroIdx() {
            for(int i=0; i<N; i++) {
                for(int j=0; j<N; j++) {
                    if(map[i][j] == 0) {
                        return new int[]{i, j};
                    }
                }
            }
            return new int[]{-1, -1};
        }
    
        private static boolean isValidPosition(int[] idx, int num) {
            int r = idx[0];
            int c = idx[1];
            // 가로 || 세로 체크
            for(int i=0; i<N; i++) {
                if(map[r][i] == num || map[i][c] == num) return false;
            }
            //같은 블럭 체크
            int sr = (r/3)*3;
            int sc = (c/3)*3;
    
            for(int i=sr; i<sr+3; i++) {
                for(int j=sc; j<sc+3; j++) {
                    if(map[i][j] == num) return false;
                }
            }
            return true;
        }
    
        private static void printSdoku() {
            StringBuffer ans = new StringBuffer();
            for(int i=0; i<N; i++) {
                for(int j=0; j<N; j++) {
                    ans.append(map[i][j]);
                }
                ans.append("\n");
            }
            System.out.print(ans.toString());
        }
    }
    

     

    728x90

    댓글

Designed by Tistory.