[Gold IV] 스도쿠 - 2580
성능 요약
메모리: 16048 KB, 시간: 368 ms
분류
백트래킹
제출 일자
2023년 12월 17일 16:20:12
문제 설명
스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루어진 정사각형 판 위에서 이뤄지는데, 게임 시작 전 일부 칸에는 1부터 9까지의 숫자 중 하나가 쓰여 있다.
나머지 빈 칸을 채우는 방식은 다음과 같다.
- 각각의 가로줄과 세로줄에는 1부터 9까지의 숫자가 한 번씩만 나타나야 한다.
- 굵은 선으로 구분되어 있는 3x3 정사각형 안에도 1부터 9까지의 숫자가 한 번씩만 나타나야 한다.
위의 예의 경우, 첫째 줄에는 1을 제외한 나머지 2부터 9까지의 숫자들이 이미 나타나 있으므로 첫째 줄 빈칸에는 1이 들어가야 한다.
또한 위쪽 가운데 위치한 3x3 정사각형의 경우에는 3을 제외한 나머지 숫자들이 이미 쓰여있으므로 가운데 빈 칸에는 3이 들어가야 한다.
이와 같이 빈 칸을 차례로 채워 가면 다음과 같은 최종 결과를 얻을 수 있다.
게임 시작 전 스도쿠 판에 쓰여 있는 숫자들의 정보가 주어질 때 모든 빈 칸이 채워진 최종 모습을 출력하는 프로그램을 작성하시오.
입력
아홉 줄에 걸쳐 한 줄에 9개씩 게임 시작 전 스도쿠판 각 줄에 쓰여 있는 숫자가 한 칸씩 띄워서 차례로 주어진다. 스도쿠 판의 빈 칸의 경우에는 0이 주어진다. 스도쿠 판을 규칙대로 채울 수 없는 경우의 입력은 주어지지 않는다.
출력
모든 빈 칸이 채워진 스도쿠 판의 최종 모습을 아홉 줄에 걸쳐 한 줄에 9개씩 한 칸씩 띄워서 출력한다.
스도쿠 판을 채우는 방법이 여럿인 경우는 그 중 하나만을 출력한다.
풀이 방법
1. 0이라면 따로 List에 저장해준다.
2. 그럼 확인해야할건 depth가 List가 Size가 같은지 확인하고 같다면 배열 출력해준다.
3. 1부터 9까지 돌고난 뒤 위치에 들어갈 수 있는지 없는지 판단
- 들어갈 수 있다면 재귀 호출 후 0으로 다시 기존 상태로 변경
4. 들어갈 수 있는 경우
- 가로 세로에 해당 값이 존재하지 않아야한다.
- 해당 3 x 3 위치에 같은 값이 존재하면 안된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class Main {
static class EmptyPoint{
int x;
int y;
public EmptyPoint(int x, int y) {
this.x = x;
this.y = y;
}
}
static int[][] map = new int[9][9];
// 비어있는 곳을 기억하기 위한 ArrayList
static ArrayList<EmptyPoint> empty = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
for(int i = 0; i < 9; i++){
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 9; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if(map[i][j] == 0){
// 0인 위치를 기억해준다.
empty.add(new EmptyPoint(i, j));
}
}
}
dfs(0);
}
private static void dfs(int depth) {
// depth가 empty크기와 같다면 -> 전부 채워져 있는 상태
if (depth == empty.size()) {
// 출력 후 프로그램 종료 시켜준다.
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
sb.append(map[i][j] + " ");
}
sb.append("\n");
}
System.out.println(sb);
System.exit(0);
}
// 현재 depth 위치에 빈칸을 불러옴
EmptyPoint pos = empty.get(depth);
for (int i = 1; i <= 9; i++) {
// i값이 유효하게 들어가는지 확인해준다.
if (validationNumber(i, pos)) {
// i값을 넣어준 뒤 dfs 호출
map[pos.x][pos.y] = i;
dfs(depth + 1);
// 만약 dfs호출 시 유효하지 않는 경우일 수 있으니 기존 상태로 복구 시켜줌
map[pos.x][pos.y] = 0;
}
}
}
private static boolean validationNumber(int value, EmptyPoint pos) {
// 가로 줄, 세로 줄에 value값이 존재하는지 확인
for(int i = 0; i < 9; i++){
if (map[pos.x][i] == value || map[i][pos.y] == value) {
return false;
}
}
// 해당 위치 3 x 3 위치에 value값이 있는지 확인해줌
int x = (pos.x / 3) * 3;
int y = (pos.y / 3) * 3;
for(int i = x; i < x + 3; i++){
for(int j = y; j < y + 3; j++){
if(map[i][j] == value){
return false;
}
}
}
return true;
}
}
'알고리즘 - Baekjoon > Gold' 카테고리의 다른 글
[백준] 15711번 : 환상의 짝궁 Gold3(골드3) - JAVA[자바] (0) | 2023.12.18 |
---|---|
[백준] 1644번 : 소수의 연속합 Gold3(골드3) - JAVA[자바] (1) | 2023.12.17 |
[백준] 2661번 : 좋은수열 Gold4(골드4) - JAVA[자바] (0) | 2023.12.17 |
[백준] 15686번 : 치킨 배달 Gold5(골드5) - JAVA[자바] (0) | 2023.12.16 |
[백준] 9935번 : 문자열 폭발 Gold4(골드4) - JAVA[자바] (0) | 2023.12.13 |