작성일 :

문제 링크

2580번 - 스도쿠

설명

빈칸이 0으로 표시된 9 곱하기 9 스도쿠 보드가 주어질 때, 스도쿠 규칙을 만족하도록 빈칸을 채우는 문제입니다. 입력은 항상 해가 존재합니다.


접근법

빈칸을 위에서 아래로, 왼쪽에서 오른쪽으로 순회하며 백트래킹으로 채웁니다.

각 칸에서 1부터 9까지 순서대로 숫자를 시도합니다. 해당 숫자가 같은 행, 같은 열, 같은 3 곱하기 3 박스에 이미 존재하면 건너뜁니다. 유효한 숫자를 찾으면 배치하고 다음 칸으로 넘어갑니다.

유효성 검사를 빠르게 하기 위해 행, 열, 박스별로 각 숫자의 사용 여부를 배열에 기록합니다. 숫자를 배치할 때 해당 위치를 참으로 표시하고, 되돌릴 때 거짓으로 복원합니다.

모든 칸을 채우면 해를 찾은 것이므로 출력하고 종료합니다.



Code

C#

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;

class Program {
  const int N = 9;
  static int[,] board = new int[N, N];
  static bool[,] row = new bool[N, 10];
  static bool[,] col = new bool[N, 10];
  static bool[,] box = new bool[N, 10];

  static bool Dfs(int idx) {
    if (idx == N * N) return true;
    var r = idx / N;
    var c = idx % N;
    if (board[r, c] != 0) return Dfs(idx + 1);

    var b = (r / 3) * 3 + (c / 3);
    for (var num = 1; num <= 9; num++) {
      if (row[r, num] || col[c, num] || box[b, num]) continue;
      board[r, c] = num;
      row[r, num] = col[c, num] = box[b, num] = true;
      if (Dfs(idx + 1)) return true;
      board[r, c] = 0;
      row[r, num] = col[c, num] = box[b, num] = false;
    }
    return false;
  }

  static void Main() {
    for (var r = 0; r < N; r++) {
      var parts = Console.ReadLine()!.Split();
      for (var c = 0; c < N; c++) {
        var v = int.Parse(parts[c]);
        board[r, c] = v;
        if (v != 0) {
          row[r, v] = true;
          col[c, v] = true;
          box[(r / 3) * 3 + (c / 3), v] = true;
        }
      }
    }

    Dfs(0);

    for (var r = 0; r < N; r++) {
      for (var c = 0; c < N; c++) {
        Console.Write(board[r, c]);
        if (c + 1 != N) Console.Write(" ");
      }
      Console.WriteLine();
    }
  }
}

C++

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>
using namespace std;

const int N = 9;
int board[N][N];
bool rowUsed[N][10], colUsed[N][10], boxUsed[N][10];

bool dfs(int idx) {
  if (idx == N * N) return true;
  int r = idx / N, c = idx % N;
  if (board[r][c] != 0) return dfs(idx + 1);

  int b = (r / 3) * 3 + (c / 3);
  for (int num = 1; num <= 9; num++) {
    if (rowUsed[r][num] || colUsed[c][num] || boxUsed[b][num]) continue;
    board[r][c] = num;
    rowUsed[r][num] = colUsed[c][num] = boxUsed[b][num] = true;
    if (dfs(idx + 1)) return true;
    board[r][c] = 0;
    rowUsed[r][num] = colUsed[c][num] = boxUsed[b][num] = false;
  }
  return false;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  for (int r = 0; r < N; r++) {
    for (int c = 0; c < N; c++) {
      cin >> board[r][c];
      int v = board[r][c];
      if (v != 0)
        rowUsed[r][v] = colUsed[c][v] = boxUsed[(r/3)*3 + (c/3)][v] = true;
    }
  }

  dfs(0);

  for (int r = 0; r < N; r++) {
    for (int c = 0; c < N; c++) {
      cout << board[r][c];
      if (c + 1 != N) cout << " ";
    }
    cout << "\n";
  }

  return 0;
}