🟦/백준

[골드 4] 스도쿠

진뚱이용 2023. 7. 31. 15:32

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

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;

		int[][] arr = new int[9][9];

		for (int i = 0; i < 9; i++) {
			String input_line = br.readLine();
			for (int j = 0; j < 9; j++) {
				arr[i][j] = input_line.charAt(j) - '0';
			}
		}

		//////////////////////////////////////////////////////

		// 가로
		boolean[][] i_visited = new boolean[9][10];
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				i_visited[i][arr[i][j]] = true;
			}
		}
		// 세로
		boolean[][] j_visited = new boolean[9][10];
		for (int j = 0; j < 9; j++) {
			for (int i = 0; i < 9; i++) {
				j_visited[j][arr[i][j]] = true;
			}
		}

		// 사각형
		boolean[][][] visited = new boolean[3][3][10];
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				for (int y = 0; y < 3; y++) {
					for (int x = 0; x < 3; x++) {
						visited[i][j][arr[3 * i + y][3 * j + x]] = true;
					}
				}
			}
		}

		recursion(arr, i_visited, j_visited, visited, 0);
	}

	public static void recursion(int[][] arr, boolean[][] i_visited, boolean[][] j_visited, boolean[][][] visited,
			int index) {
		if (index == 81) {
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					System.out.print(arr[i][j]);
				}
				System.out.println("");
			}
			System.exit(0);
		}

		if (arr[index / 9][index % 9] == 0) {
			for (int num = 1; num <= 9; num++) {
				if (!i_visited[index / 9][num] && !j_visited[index % 9][num]
						&& !visited[index / 9 / 3][index % 9 / 3][num]) {
					i_visited[index / 9][num] = true;
					j_visited[index % 9][num] = true;
					visited[index / 9 / 3][index % 9 / 3][num] = true;
					arr[index / 9][index % 9] = num;
					recursion(arr, i_visited, j_visited, visited, index + 1);
					i_visited[index / 9][num] = false;
					j_visited[index % 9][num] = false;
					visited[index / 9 / 3][index % 9 / 3][num] = false;
					arr[index / 9][index % 9] = 0;
				}
			}
		}
		else {
			recursion(arr, i_visited, j_visited, visited, index + 1);
		}
	}
}

i_visited[3] -> 위에서 4번째 줄의 숫자 visited

j_visited[2] -> 왼쪽에서 3번째 줄의 숫자 visited

visited[2][1] -> 맨 밑줄 왼쪽 오른쪽 가운데의 3*3의 숫자 visited

 

brute force로 푼다

그냥 조건에 맞으면 숫자 넣고 방문처리하고 한 칸 전진하고 딱히 아이디어는 없음

visited 배열 index가 복잡했었다