본문 바로가기
Algorithm/Baekjoon

Baekjoon 2239 스도쿠 JAVA

by Hunveloper 2022. 4. 10.
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자리의 수가 제일 작은 경우를 출력한다.

풀이

모든 빈자리에 1~9의 값을 넣어가며 답을 찾는 브루트포스 문제이다.

시간을 단축하기 위해 백트래킹 기법을 활용하였다.

코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {
	static int[][] map;

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		map = new int[9][9];// , temp = new int[9][9];
		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';
		}

		sudoku(0, 0);

		System.out.println("결과");
	}

	private static void sudoku(int row, int col) throws Exception {

		if (col == 9) {
			sudoku(row + 1, 0);
			return;
		}
		if (row == 9) {
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++)
					bw.write(map[i][j] + '0');
				bw.write("\n");
			}
			bw.close();
			System.exit(0);
		}

		// row 먼저 증가, row가 끝까지 올라가면 col증가
		if (map[row][col] == 0) {
			for (int i = 1; i <= 9; i++) {
				if (check(row, col, i)) {
					map[row][col] = i;
					sudoku(row, col + 1);
				}
			}
			map[row][col] = 0;
			return;
		}
		sudoku(row, col + 1);
	}

	private static boolean check(int row, int col, int val) {
		// 가로체크
		for (int j = 0; j < 9; j++)
			if (map[row][j] == val)
				return false;

		// 세로체크
		for (int i = 0; i < 9; i++)
			if (map[i][col] == val)
				return false;

		// 부분체크
		for (int i = (row / 3) * 3; i < ((row / 3) * 3) + 3; i++) {
			for (int j = (col / 3) * 3; j < ((col / 3) * 3) + 3; j++) {
				if (map[i][j] == val)
					return false;
			}
		}
		// 모든 검사 완료시 가능한 조합임
		return true;
	}
}

 

728x90
728x90

댓글