-
[백준]2239: 스도쿠(java)Algorithm/백준 2022. 4. 9. 20:57728x90
스도쿠는 매우 간단한 숫자 퍼즐이다. 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'Algorithm > 백준' 카테고리의 다른 글
[백준]1941: 소문난 칠공주(java) (0) 2022.04.11 [백준]21610: 마법사 상어와 비바라기(java) (0) 2022.04.10 [백준]16986: 인싸들의 가위바위보(java) (0) 2022.04.08 [백준]3190: 뱀(java) (0) 2022.04.07 [백준]16235: 나무 재테크(java) (0) 2022.04.06 - 12095번 문제에 있는 소스로 풀 수 있는 입력만 주어진다.