Seren dev's blog

https://www.acmicpc.net/problem/2580

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루

www.acmicpc.net

 

1. 풀이

DFS를 사용하여 스도쿠의 빈 칸에 모든 수를 집어넣고 각 경우마다 스도쿠가 될 수 있는지 체크한다.

 

2. 로직

1. 스도쿠의 빈 칸 좌표를 ArrayList<int[]> points에 넣는다.

2. sudoku(idx:0)을 호출한다. 이 때 idx는 points의 인덱스다.

3. points에서 좌표를 꺼내고, for문으로 1~9까지 해당 좌표에 들어갈 수 있는지 check() 함수를 통해 체크한다.

  • 들어갈 수 있다면 해당 좌표에 숫자를 넣고, sudoku(idx+1)을 호출한다.

4. 재귀함수를 반복하여 스도쿠가 모두 완성이 되었으면 출력하고, 시스템을 종료한다.

2.1. 주의할 점

  • sudoku() 가 리턴되고 난 후, arr[tmp[0]][arr[tmp[1] = 0; 을 무조건 해주어야 한다. 그렇지 않으면, 이전 함수로 돌아갈 때 0이 아닌 숫자가 남겨져 있는 채로 return 될 수 있다.

3. 코드

<java />
import java.io.*; import java.util.*; public class Main { static int[][] arr = new int[9][9]; static ArrayList<int[]> points; static public boolean check(int row, int col, int value) { //같은 열이나 같은 행에서 같은 숫자가 있는지 체크 for (int idx = 0; idx < 9; idx++) { if (arr[row][idx] == value || arr[idx][col] == value) { return false; } } //3x3 정사각형 안에 같은 숫자가 있는지 체크 int tmpRow = (row / 3) * 3; int tmpCol = (col / 3) * 3; for (int i = tmpRow; i < tmpRow+3; i++) { for (int j = tmpCol; j < tmpCol+3; j++) { if (arr[i][j] == value) { return false; } } } return true; } static public void sudoku(int idx) { if (idx == points.size()) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) sb.append(arr[i][j] + " "); sb.append("\n"); } System.out.println(sb); System.exit(0); } int[] tmp = points.get(idx); for (int k = 1; k <= 9; k++) { if (check(tmp[0], tmp[1], k)) { arr[tmp[0]][tmp[1]] = k; sudoku(idx + 1); } arr[tmp[0]][tmp[1]] = 0; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); points = new ArrayList<>(); for (int i = 0; i < 9; i++) { StringTokenizer st = new StringTokenizer(br.readLine()); for (int j = 0; j < 9; j++) { int n = Integer.parseInt(st.nextToken()); arr[i][j] = n; if (n == 0) points.add(new int[]{i, j}); } } sudoku(0); } }
  • System.exit(0) : 프로그램을 바로 종료한다.

 


4. 다른 풀이 2

스도쿠의 빈 칸 좌표를 따로 저장하지 않고, 재귀함수의 인자로 행, 열 번호를 넘긴다.

4.1. 로직

1. sudoku(row=0, col=0)을 호출한다. 각각 스도쿠의 행, 열 번호이다.

2. arr[row][col] == 0 이라면 for문으로 1~9까지 해당 좌표에 들어갈 수 있는지 check() 함수를 통해 체크한다.

  • 들어갈 수 있다면 해당 좌표에 숫자를 넣고, sudoku(row, col+1)을 호출한다.

3. arr[row][col] == 0 이 아니라면 sudoku(row, col+1)을 호출한다.

4. col == 9 라면 sudoku(row + 1, 0);을 호출한다.

5. 재귀함수를 반복하여 row == 9가 되면, 스도쿠가 모두 완성됨을 의미한다. 스도쿠를 출력하고, 시스템을 종료한다.

4.2. 주의할 점

  • arr[row][col] == 0 이라면 반복문이 끝난 후 arr[row][col] = 0; 을 하고 리턴해주어야 한다. 그렇지 않으면, 이전 함수로 돌아갈 때 0이 아닌 숫자가 남겨져 있는 채로 return 될 수 있다.

5. 코드

<java />
import java.io.*; import java.util.*; public class Main { static int[][] arr = new int[9][9]; static public boolean check(int row, int col, int value) { //같은 열이나 같은 행에서 같은 숫자가 있는지 체크 for (int idx = 0; idx < 9; idx++) { if (arr[row][idx] == value || arr[idx][col] == value) { return false; } } //3x3 정사각형 안에 같은 숫자가 있는지 체크 int tmpRow = (row / 3) * 3; int tmpCol = (col / 3) * 3; for (int i = tmpRow; i < tmpRow+3; i++) { for (int j = tmpCol; j < tmpCol+3; j++) { if (arr[i][j] == value) { return false; } } } return true; } static public void sudoku(int row, int col) { if (col == 9) { sudoku(row + 1, 0); return; } if (row == 9) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) sb.append(arr[i][j] + " "); sb.append("\n"); } System.out.println(sb); System.exit(0); } if (arr[row][col] == 0) { for (int k = 1; k <= 9; k++) { if (check(row, col, k)) { arr[row][col] = k; sudoku(row, col + 1); } } arr[row][col] = 0; return; } sudoku(row, col+1); } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); for (int i = 0; i < 9; i++) { StringTokenizer st = new StringTokenizer(br.readLine()); for (int j = 0; j < 9; j++) { arr[i][j] = Integer.parseInt(st.nextToken()); } } sudoku(0, 0); } }

 

참고: https://st-lab.tistory.com/119

728x90
profile

Seren dev's blog

@Seren dev

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!