일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 면접합격
- RequiredArgsConstructor
- window
- SSAFY #싸피 #7기 #합격 #개발
- Java
- 싸피
- 백엔드
- 커밋옮기기
- github
- 의존성주입
- 윈도우우분투
- commit
- SQL
- mybatis
- UnsupportedOperationException
- 프로시저
- BFG
- gitlab
- 이중우선순위큐
- 프로젝트회고록
- JsonObect
- tmehz
- 삼성 #교육 #개발자 #웹
- 백준
- treeset
- pymysql
- SSAFY
- IntelliJ
- 추가합격
- BOJ
- Today
- Total
데굴데굴 굴러가는 개발 블로그
백준 2239 스도쿠 ( java ) 본문
전형적인 백트래킹 문제라는데 사실 아직 문제를 보면 딱 ㅇㅇ로 푸는거구나~ 하는 생각이 안드는 경우가 많다.
왜 백트래킹을 쓰는지에 대해 생각을 해보니
1. 일단 완탐을 해야 하는거 같지만
2. 한번 완료하면 더이상 탐색을 할 필요가 없음 (많은 정답중에 사전식으로 하나만 출력하기 때문)
3. 따라서 해당 경우를 가지치기를 하기 위해서 -> 백트래킹 사용
이런식으로 생각해야 하지 않을까 싶다.
개인적으로 백트래킹이라는 냄새를 맡으면 조금 쉬운 문제가 아닐까..? 싶다
DP를 풀다와서 그런가 실버DP문제보다 골드문제가 더 쉬운건... 기분탓이겠지...
풀이과정
- map[9][9]에 스도쿠를 입력 받아준다.
- 모든 칸을 너비기준으로 탐색해야 하기 때문에 DFS가 적합
- dfs는 depth를 기준으로 depth == 81 ( 9 * 9 = 81 이므로) 일때 탐색을 종료
- depth = 현재 위치의 행 x 열 이므로 현재 위치는 (행) depth / 9 , (열) depth % 9
(탐색 과정)
- flag (스도쿠가 완성되면 더이상 진행을 안하기 위한 boolean 변수)
- 현재 위치가 0 인지 체크 ( 이미 스도쿠가 채워져있다면 다음 탐색을 진행하면 되기 때문)
- 숫자 1~9 까지 해당 칸에 넣어보면서 DFS 진행
해당 칸에 n이라는 숫자가 들어갈 수 있는지 체크 -> 불가능하면 다음 숫자로 continue
가능하다면 현재 위치에 n을 넣은 뒤 DFS(depth+1) 진행
진행 시킨뒤 또 다른 숫자도 가능한지 확인해야 하기 때문에 현재 위치의 값을 이전상태로 돌려 놓아야한다.
(이부분을 놓쳐서 조금 고생했다)
package Baekjoon.Gold;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
/**
* {@auther} : daeun
* @since : 2022-04-06
* link : https://www.acmicpc.net/problem/2239
* type : 구현, 백트래킹
* */
public class 백준_G5_스도쿠 {
static int[][] map = new int[9][9];
static boolean flag; // 스도쿠가 완성되었는지
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 9; i++) {
String str = br.readLine();
for (int j = 0; j < 9; j++) {
map[i][j] = str.charAt(j) - '0';
}
}
// 사전식 출력 -> 제일 작은 값부터 채워넣자 (1 ~ 9)
// 백트래킹 조건 -> 이미 스토쿠가 완성되었거나, 같은 수가 가로 , 세로 줄에 존재하거나, 3*3 안에 같은 수가 존재하는 경우
dfs(0);
for(int r=0; r<9; r++){
for(int c=0; c<9; c++){
sb.append(map[r][c]);
}
sb.append("\n");
}
System.out.println(sb.toString());
}
public static void dfs(int depth) {
if (depth == 81) { // 9 * 9 = 81칸 -> 0~80까지 돌면 81칸이므로 마지막 호출 depth : 81
flag = true; // 스도쿠 완성
return;
}
int row = depth / 9; // 행
int col = depth % 9; // 열
if(map[row][col] != 0){ // 채워진 곳인지 확인하기 -> 이미 채워진 곳이라면 dfs 탐색 진행
dfs(depth+1);
}else{ // 채워야 할 공간이라면
for(int i=1; i<=9; i++){
if(!isOk(row,col,i)) continue; // 불가능한 경우 pass
map[row][col] = i; // map에 i를 넣은 채로 dfs 진행해보기
dfs(depth+1);
if(flag) return; // 스도쿠가 완성되었다면 return(종료)
map[row][col] = 0; // 다시 진행해야 하므로 -> map을 이전 상태로 복구시켜놓기
}
}
}
public static boolean isOk(int row, int col, int n) {
// 가로줄, 세로줄에 n 이 있는지
for(int i=0; i<9; i++){
if(map[row][i] == n) return false;
if(map[i][col] == n) return false;
}
// 3*3 사각형에 n이 있는지
int sR = row / 3;
int sC = col / 3;
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
if(map[i+3*sR][j+3*sC] == n) return false;
}
}
return true; // 조건 전부 충족할 경우
}
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
백준 BOJ 1967 JAVA / 트리의 지름 (0) | 2023.01.25 |
---|---|
백준 2309 일곱 난쟁이 JAVA (0) | 2022.02.15 |