Skip to content

Conversation

@kokeunho
Copy link
Collaborator

@kokeunho kokeunho commented Jul 1, 2025

๐Ÿ”— ๋ฌธ์ œ ๋งํฌ

[BOJ] ์Šค๋„์ฟ 
https://www.acmicpc.net/problem/2580

โœ”๏ธ ์†Œ์š”๋œ ์‹œ๊ฐ„

1h30m

โœจ ์ˆ˜๋„ ์ฝ”๋“œ

๋ฐฑํŠธ๋ž˜ํ‚น์œผ๋กœ ๋นˆ์นธ์„ ๋ชจ๋‘ ์ฑ„์šฐ๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์šฐ์„  map์„ ์ž…๋ ฅ ๋ฐ›์œผ๋ฉด์„œ ๋นˆ์นธ์˜ ์ขŒํ‘œ๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋นˆ์นธ ์ขŒํ‘œ๋งˆ๋‹ค ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์ˆซ์ž ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
์ด๋•Œ ํ•ด๋‹น ์ขŒํ‘œ์˜ ํ–‰, ์—ด ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ขŒํ‘œ๊ฐ€ ํฌํ•จ๋œ 3 * 3 ๋ฐ•์Šค ๋‚ด์—์„œ๋„ ๋”ฐ์ ธ์„œ
ํ•ด๋‹น ์ขŒํ‘œ์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์ˆซ์ž ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฝ‘์•„์•ผํ•ฉ๋‹ˆ๋‹ค.
(์Šค๋„์ฟ ๋ฅผ ์ž˜ ์•ˆํ•ด๋ณด๊ณ  ๋ฌธ์ œ๋„ ์ œ๋Œ€๋กœ ์•ˆ ์ฝ์–ด์„œ 3*3 ๋ฐ•์Šค๋„ ๋”ฐ์ ธ์•ผํ•˜๋Š”์ง€ ๋ชจ๋ฅด๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค..)

์žฌ๊ท€์ ์œผ๋กœ sudoku ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋‹ค
ํ•จ์ˆ˜ ํ˜ธ์ถœ ํšŸ์ˆ˜๊ฐ€ ๋นˆ์นธ์˜ ๊ฐฏ์ˆ˜์™€ ๊ฐ™์•„์กŒ์„ ๊ฒฝ์šฐ, ๋ชจ๋“  ๋นˆ์นธ์„ ์ฑ„์› ๋‹ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ
๊ทธ ์‹œ์ ์˜ map์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ๋‚ด์šฉ

Copy link
Collaborator

@kangrae-jo kangrae-jo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋ฐฑํŠธ๋ž˜ํ‚น์„ ์ดํ•ดํ•˜๊ณ ์žˆ์œผ๋ฉด ์ž˜ ํ’€์ˆ˜์žˆ๋Š” ๋ฌธ์ œ์˜€๋„ค์š”.

์ €๋Š” ์ œ์ผ ์ฒ˜์Œ์— ๋ฌธ์ œ๋ฅผ ์ฝ๊ณ  ์‚ฌ๋žŒ์ด ํ‘ธ๋Š”๊ฒƒ ๋งˆ๋ƒฅ ํ™•์ •๋œ 0์„ ๋ฐ”๊ฟ”๋†“๋Š” ๋ฐฉ๋ฒ•์„ ๋– ์˜ฌ๋ฆฌ๋ ค๊ณ  ํ–ˆ์–ด์š”.
๊ทธ ๋ฐฉ๋ฒ•์€ 3๋ถ„๋งŒ์— ์ ‘์—ˆ์Šต๋‹ˆ๋‹ค.
๊ฑฐ์˜ ai๋ชจ๋ธ ์ˆ˜์ค€์˜ ๊ฐœ๋ฐœ์ด ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™๋”๊ตฐ์š”.
๊ทธ๋ฆฌ๊ณ  ์–ด์ฐจํ”ผ ๊ทธ๋Ÿฐ 0์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์“ธ๋ชจ์—†๋Š” ํ–‰๋™์ด ๋˜๋ฒ„๊ธฐ๋•Œ๋ฌธ์ด์ฃ .

๊ทธ ๋’ค์— ์ƒ๊ฐ๋‚œ ๋ฐฉ์‹์ด ๋ฐฑํŠธ๋ž˜ํ‚น์ž…๋‹ˆ๋‹ค.
bool ๋ฐฐ์—ด์„ ๋‘๊ณ  ๊ฐ€๋กœ ์„ธ๋กœ ๋„ค๋ชจ๋ฅผ ๊ฒ€์‚ฌํ•ด์„œ ํ˜„์žฌ ์ขŒํ‘œ์— ๋†“์„ ์ˆ˜ ์žˆ๋Š” ๋…€์„๋“ค์„ ๋„ฃ์œผ๋ฉฐ backtracking ํ•˜๋Š” ๋ฐฉ์‹์ด์ฃ 

๊ตฌ์กฐ๋Š” ํ•œ 40๋ถ„ ์ •๋„์— ์™„์„ฑ์„ ํ–ˆ๋Š”๋ฐ, ๋ฒ ์ด์Šค์ผ€์ด์Šค๋ฅผ ๋„ฃ์ง€ ์•Š์•˜๊ณ  ๊ทธ๊ฑธ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•ด์„œ ๋‹ค๋ฅธ๊ณณ๋งŒ ๊ณ ์น˜๋‹ค ์‹œ๊ฐ„์ด ํ•œ 15๋ถ„ ํ˜๋ €๋„ค์š”.
๊ณ ์น˜๊ธฐ ์ „์—๋Š” 1% ์‹œ๊ฐ„์ดˆ๊ณผ...์—”๋”ฉ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฒ ์ด์Šค์ผ€์ด์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ  ๋‹ค์‹œ ์ œ์ถœํ•ด๋ดค์Šต๋‹ˆ๋‹ค.
์ด๋ฒˆ์—” 80% ์ฏค์—์„œ ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋œจ๋”๋ผ๊ตฌ์š”.

๋„์ €ํžˆ ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์–ด์„œ gpt์— ๋„ฃ์–ด๋ดค์Šต๋‹ˆ๋‹ค.
map์€ RB Tree์—ฌ์„œ ์‚ฝ์ž…์†๋„๊ฐ€ O(1)์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด ๋ฌธ์ œ์˜€๋„ค์š”...
9๊ฐœ ์ •๋„๋ฉด ์ƒ๊ด€ ์—†์„ ์ค„ ์•Œ์•˜๋Š”๋ฐ...

๊ทธ๋ž˜์„œ map์„ vector๋กœ ๋ฐ”๊พธ์–ด์ฃผ๋‹ˆ ๋ฐ”๋กœ ์„ฑ๊ณต์ด์—ˆ์Šต๋‹ˆ๋‹ค.

#include <iostream>
#include <vector>

using namespace std;

const int EMPTY = 0;
const int N = 9;

vector<vector<int>> board(N, vector<int>(N, EMPTY));

void checkRow(vector<bool>& cannot, int x) {
    for (int y = 0; y < N; y++) {
        cannot[board[y][x]] = true;
    }
}

void checkCol(vector<bool>& cannot, int y) {
    for (int x = 0; x < N; x++) {
        cannot[board[y][x]] = true;
    }
}

void checkSqr(vector<bool>& cannot, int y, int x) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cannot[board[(y / 3) * 3 + i][(x / 3) * 3 + j]] = true;
        }
    }
}

bool backtracking(int y_, int x_) {
    for (int y = y_; y < N; y++) {
        for (int x = 0; x < N; x++) {
            if (board[y][x] == EMPTY) {
                vector<bool> cannot(N + 1, false);  // (y, x)์— ๋†“์„ ์ˆ˜ ์—†๋Š” ์ˆ˜๋“ค์€ true
                checkRow(cannot, x);
                checkCol(cannot, y);
                checkSqr(cannot, y, x);

                for (int candi = 1; candi <= N; candi++) {
                    if (!cannot[candi]) {
                        board[y][x] = candi;
                        if (backtracking(y, x)) return true;
                        board[y][x] = EMPTY;
                    }
                }
                return false;
            }
        }
    }
    return true;
}

int main() {
    ios_base::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);

    for (int y = 0; y < N; y++) {
        for (int x = 0; x < N; x++) {
            cin >> board[y][x];
        }
    }

    backtracking(0, 0);

    cout << endl;
    for (int y = 0; y < N; y++) {
        for (int x = 0; x < N; x++) {
            cout << board[y][x] << " ";
        }
        cout << endl;
    }

    return 0;
}

Copy link
Member

@9kyo-hwang 9kyo-hwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ตฌ์กฐ๊ฐ€ ์•ฝ๊ฐ„ N-Queen ๋ฌธ์ œ๋ž‘ ๋น„์Šทํ•œ ๊ฒƒ ๊ฐ™์•„์š”. ๋นˆ ์นธ์— ๋Œ€ํ•ด 1๋ถ€ํ„ฐ 9๊นŒ์ง€ ์ˆ˜๋ฅผ ๋Œ€์ž…ํ•ด๋ณด๊ณ , ๊ทธ๊ฒŒ ๊ฐ€๋Šฅํ•œ ์ง€ ๊ฒ€์‚ฌํ•ด์„œ ๊ฐ€๋Šฅํ•˜๋ฉด true, ์•„๋‹ˆ๋ผ๋ฉด false. ๋”ฑ Promising & Backtracking ๊ตฌ์กฐ๊ฐ€ ๋˜๋”๋ผ๊ตฌ์š” ใ…‹ใ…‹

์ฝ”๋“œ

#include <iostream>
#include <array>
#include <vector>

#define EMPTY 0

using namespace std;

vector<pair<int, int>> v;
array<array<int, 9>, 9> arr;

bool Promising(size_t count) {
  const auto &[empty_x, empty_y] = v[count];

  for (int col = 0; col < 9; col++) { // ํ–‰์— ๊ฒน์น˜๋Š” ์ˆซ์ž ์žˆ๋Š” ์ง€ ํ™•์ธ
    if ((col != empty_y) && (arr[empty_x][col] == arr[empty_x][empty_y]))
      return false;
  }

  for (int row = 0; row < 9; row++) { // ์—ด์— ๊ฒน์น˜๋Š” ์ˆซ์ž ์žˆ๋Š” ์ง€ ํ™•์ธ
    if ((row != empty_x) && (arr[row][empty_y] == arr[empty_x][empty_y]))
      return false;
  }

  // ๊ตฌ์—ญ์— ๊ฒน์น˜๋Š” ์ˆซ์ž ์žˆ๋Š” ์ง€ ํ™•์ธ
  int area_x = empty_x / 3;
  int area_y = empty_y / 3;
  for (int row = area_x * 3; row < area_x * 3 + 3; row++) {
    for (int col = area_y * 3; col < area_y * 3 + 3; col++) {
      if ((row != empty_x) && (col != empty_y) && (arr[empty_x][empty_y] == arr[row][col]))
        return false;
    }
  }

  return true;
}

bool Sudoku(size_t count = 0) {
  if (count == v.size())
    return true;

  const auto &[x, y] = v[count];
  for (int i = 1; i <= 9; i++) {
    arr[x][y] = i;
    if (!Promising(count))
      continue;

    if (Sudoku(count + 1))
      return true;
  }
  arr[x][y] = 0;
  return false;
}

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

  for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
      cin >> arr[i][j];
      if (arr[i][j] == EMPTY)
        v.emplace_back(i, j);
    }
  }

  if (Sudoku()) {
    for(const auto &i : arr) {
      for(const auto &j : i) {
        cout << j << " ";
      }
      cout << "\n";
    }
  }
  return 0;
}

๊ทธ๋Ÿฐ๋ฐ ์ด๋Ÿฌ๋ฉด ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งค ๋ฒˆ 9x9 ๋ณด๋“œ์— ๋Œ€ํ•ด ํ˜„์žฌ ์Šค๋„์ฟ ๊ฐ€ ์™„์„ฑ๋˜์—ˆ๋Š”์ง€ ๋‹ค ํ›‘์–ด๋ณด๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .
image

์ด๋ฅผ ๊ฐ ํ–‰/์—ด/3x3 ๋ฐ•์Šค ๊ตฌ๊ฐ„ ๋ณ„๋กœ ์‚ฌ์šฉ๋œ ์ˆซ์ž๋ฅผ ์บ์‹ฑํ•˜๋Š” ์‹์œผ๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ์„ ๋œ ์ฝ”๋“œ

#include <bits/stdc++.h>

using namespace std;

constexpr int EMPTY = 0;
int board[9][9];
vector<pair<int, int>> empties;
bool rowUsed[9][10], colUsed[9][10], boxUsed[9][10];

bool dfs(int idx = 0) {
    if(idx == empties.size()) {
        return true;
    }
    
    const auto& [r, c] = empties[idx];
    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;
        }
        
        rowUsed[r][num] = colUsed[c][num] = boxUsed[b][num] = false;
        board[r][c] = EMPTY;
    }
    
    return false;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    for(int i = 0; i < 9; ++i) {
        for(int j = 0; j < 9; ++j) {
            cin >> board[i][j];
            if(board[i][j] == 0) {
                empties.emplace_back(i, j);
            } else {
                int num = board[i][j];
                rowUsed[i][num] = true;
                colUsed[j][num] = true;
                boxUsed[(i / 3) * 3 + j / 3][num] = true;
            }
        }
    }
    
    dfs();
    
    for(int i = 0; i < 9; ++i) {
        for(int j = 0; j < 9; ++j) {
            cout << board[i][j] << " ";
        }
        cout << "\n";
    }

    return 0;
}

image


GPT๊ฐ€ ๋˜๊ฒŒ ๋…ํŠนํ•œ ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ด์คฌ๋Š”๋ฐ ๋ญ”๊ฐ€ ๋งŽ์ด ๋…ํŠนํ•œ ๊ธฐ๋ฒ•์ด๋ผ ๊ถ๊ธˆํ•˜์‹  ๋ถ„์€ ์ฝ์–ด๋ณด์…”๋„...?

๋น„ํŠธ๋งˆ์Šคํ‚น + MRV

#include <bits/stdc++.h>
using namespace std;

// 9ร—9 ์Šค๋„์ฟ 
int board[9][9];
// ํ–‰, ์—ด, ๋ธ”๋ก๋ณ„๋กœ ์‚ฌ์šฉ๋œ ์ˆซ์ž๋ฅผ ๋น„ํŠธ๋งˆ์Šคํฌ๋กœ ๊ด€๋ฆฌ
// ๋งˆ์Šคํฌ์˜ ๋น„ํŠธ k(1โ‰คkโ‰ค9)๊ฐ€ 1์ด๋ฉด ์ˆซ์ž k๊ฐ€ ์ด๋ฏธ ์‚ฌ์šฉ๋œ ์ƒํƒœ
int rowMask[9], colMask[9], boxMask[9];
// ๋นˆ ์นธ ์ขŒํ‘œ ๋ชฉ๋ก
vector<pair<int,int>> empties;

// ์žฌ๊ท€ ํƒ์ƒ‰: filled๊ฐœ๋ฅผ ์ฑ„์šด ์ƒํƒœ์—์„œ ๋‚˜๋จธ์ง€๋ฅผ ์ฑ„์šฐ๋Š” ํ•จ์ˆ˜
bool solve(int filled = 0) {
    if (filled == (int)empties.size())
        return true;  // ๋ชจ๋‘ ์ฑ„์› ์œผ๋ฉด ์„ฑ๊ณต

    // MRV: ๋‚จ์€ ํ›„๋ณด๊ฐ€ ๊ฐ€์žฅ ์ ์€ ์นธ์„ ์ฐพ์•„์„œ ์•ž์œผ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค
    int best = -1, minCount = 10;
    for (int i = filled; i < (int)empties.size(); ++i) {
        auto [r, c] = empties[i];
        int b = (r/3)*3 + c/3;
        int avail = ~(rowMask[r] | colMask[c] | boxMask[b]) & 0x3FE;
        int cnt = __builtin_popcount(avail);
        if (cnt < minCount) {
            minCount = cnt;
            best = i;
            if (cnt == 0) break;  // ํ›„๋ณด๊ฐ€ ์—†์œผ๋ฉด ๋ฐ”๋กœ ์‹คํŒจ
        }
    }
    if (minCount == 0) return false;

    // ํ›„๋ณด ์ ์€ ์นธ์„ filled ์œ„์น˜๋กœ ์Šค์™‘
    swap(empties[filled], empties[best]);
    auto [r, c] = empties[filled];
    int b = (r/3)*3 + c/3;
    int avail = ~(rowMask[r] | colMask[c] | boxMask[b]) & 0x3FE;

    // ๊ฐ€๋Šฅํ•œ ์ˆซ์ž ํ•˜๋‚˜์”ฉ ์‹œ๋„
    while (avail) {
        int bit = avail & -avail;             // ๊ฐ€์žฅ ๋‚ฎ์€ ๋น„ํŠธ
        int d   = __builtin_ctz(bit);         // ๊ทธ ๋น„ํŠธ์˜ ์ธ๋ฑ์Šค = ์ˆซ์ž
        avail ^= bit;

        // ์ˆซ์ž d๋ฅผ ๋†“๋Š”๋‹ค
        board[r][c] = d;
        rowMask[r] |= bit;
        colMask[c] |= bit;
        boxMask[b] |= bit;

        if (solve(filled+1))
            return true;

        // backtrack
        rowMask[r] ^= bit;
        colMask[c] ^= bit;
        boxMask[b] ^= bit;
        board[r][c] = 0;
    }

    // ์›์œ„์น˜ ๋ณต๊ตฌ
    swap(empties[filled], empties[best]);
    return false;
}

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

    // ์ž…๋ ฅ๊ณผ ์ดˆ๊ธฐ ๋งˆ์Šคํฌ ์„ค์ •
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            cin >> board[i][j];
            if (board[i][j]) {
                int bit = 1 << board[i][j];
                rowMask[i] |= bit;
                colMask[j] |= bit;
                boxMask[(i/3)*3 + j/3] |= bit;
            } else {
                empties.emplace_back(i, j);
            }
        }
    }

    solve();

    // ๊ฒฐ๊ณผ ์ถœ๋ ฅ
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            cout << board[i][j] << ' ';
        }
        cout << "\n";
    }
    return 0;
}

image
image


์‹ฌ์ง€์–ด ํฌ๋ˆ„์Šค X ๋ผ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ทนํ•œ์œผ๋กœ ๋น ๋ฅด๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋Š”๋ฐ ์ฝ๋‹ค๋ณด๋‹ˆ ์–ด์ง€๋Ÿฌ์›Œ์„œ ์ „ ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค ใ…‹ใ…‹...

Copy link
Collaborator

@wnsmir wnsmir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ทผํ˜ธ๋‹˜ ๋ฌธ์ œ๋ฅผ ๋ณด๋ฉด ๋ฐฑํŠธ๋ž˜ํ‚น ํ˜น์€ ์™„์ „ํƒ์ƒ‰๋ฌธ์ œ๊ฐ€ ๋งŽ์€๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์ œ๊ฐ€ ์žฌ๊ท€๋ถ€๋ถ„์ด ์•ฝํ•œ๋ฐ ๋•๋ถ„์— ๋„์›€์ด ๋งŽ์ด ๋ฉ๋‹ˆ๋‹ค ใ… ใ…œ

์ฒ˜์Œ์—๋Š” ๋นˆ์นธ๋งˆ๋‹ค 1๋ถ€ํ„ฐ 9๊นŒ์ง€ ๋‹ค ๋„ฃ์–ด๋ณด๋Š”์‹์œผ๋กœ ํ–ˆ๋‹ค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์ดˆ๊ณผ๋‚˜์„œ
๋‚จ์€ ํ›„๋ณด๊ฐ€ ์ ์€ ์นธ๋ถ€ํ„ฐ ๋„ฃ์–ด๋ณด๋„๋ก ์ง‘ํ•ฉ์„ ์ด์šฉํ•ด์„œ ๋ถ„๊ธฐ๋ฅผ ์ตœ์†Œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

import sys
input = sys.stdin.readline

# 1) ์ž…๋ ฅ ๋ฐ›์œผ๋ฉด์„œ board, rows, cols, boxes, empties ๊ตฌ์„ฑ
board = [list(map(int, input().split())) for _ in range(9)]
rows = [set(range(1,10)) for _ in range(9)]
cols = [set(range(1,10)) for _ in range(9)]
boxes= [set(range(1,10)) for _ in range(9)]
empties = []

for r in range(9):
    for c in range(9):
        v = board[r][c]
        if v:
            rows[r].remove(v)
            cols[c].remove(v)
            boxes[(r//3)*3 + (c//3)].remove(v)
        else:
            empties.append((r,c))

# 2) DFS ํ•จ์ˆ˜: ๋นˆ ์นธ์ด ์—†์œผ๋ฉด True ๋ฐ˜ํ™˜
def dfs():
    if not empties:
        return True

    # ๋‚จ์€ ๋นˆ ์นธ ์ค‘ ํ›„๋ณด ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ์ ์€ ์นธ์„ ์„ ํƒ
    best = min(
        empties,
        key=lambda x: len(rows[x[0]] & cols[x[1]] & boxes[(x[0]//3)*3 + (x[1]//3)])
    )
    r, c = best
    b = (r//3)*3 + (c//3)
    candidates = rows[r] & cols[c] & boxes[b]  # ํ›„๋ณด ์ˆซ์ž ์ง‘ํ•ฉ

    if not candidates:
        return False

    empties.remove(best)
    for v in candidates:
        # ๋ฐฐ์น˜
        board[r][c] = v
        rows[r].remove(v)
        cols[c].remove(v)
        boxes[b].remove(v)

        if dfs():
            return True

        # ๋˜๋Œ๋ฆฌ๊ธฐ
        board[r][c] = 0
        rows[r].add(v)
        cols[c].add(v)
        boxes[b].add(v)

    empties.append(best)
    return False

# 3) ์‹คํ–‰ ๋ฐ ์ถœ๋ ฅ
dfs()
out = []
for row in board:
    out.append(" ".join(map(str, row)))
sys.stdout.write("\n".join(out))

Copy link
Collaborator

@g0rnn g0rnn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋ฌธ์ œ๋ฅผ ์ž˜ ์•ˆํ’€๋‹ค๋ณด๋‹ˆ ๋ฐฑํŠธ๋ ˆํ‚น์ด ์ข€ ์–ด๋ ค์›Œ์กŒ๋„ค์š”.. ์˜ˆ์ „์—” ๋จธ๋ฆฌ ์†์— ๋ฐฑํŠธ๋ ˆํ‚น๋งŒ ๋– ์˜ค๋ฅด๋˜ ์‹œ์ ˆ์ด ์žˆ์—ˆ๋Š”๋ฐ.. ํ—ˆํ—ˆ

๊ทผ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žฌ๋ฐŒ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑํŠธ๋ ˆํ‚น์„ ์ข€ ์žฌ๋ฐŒ๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋А๋‚Œ์ด๋„ค์š”.

๊ทผํ˜ธ๋‹˜๊ณผ ๋‹ค๋ฅธ๋ถ„๋“ค์€ ์บ์‹ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์†๋„๋ฅผ ๋†’์ธ๊ฑฐ ๊ฐ™์€๋ฐ, ์ „ ๋ชจ๋“  ์นธ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ 0์ด ์•„๋‹ˆ๋ผ๋ฉด ๋‹ค์Œ ์นธ์œผ๋กœ ๋„˜์–ด๊ฐ€๊ณ , ๊ทธ๋ ‡๊ฒŒ ๋ชจ๋“  ์นธ์„ ์ˆœํšŒํ•œ๋‹ค๋ฉด ์ข…๋ฃŒํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์นธ์„ ์ˆœํšŒํ•˜๊ณ  x์™€ y๊ฐ€ ๋ฒ”์œ„ ๋ฐ–์œผ๋กœ ๋„˜์–ด๊ฐ”์„ ๋• ์Šค๋„์ฟ ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฑ„์› ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

package beakjoon;

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

public class Sol2580 {

    static int[][] board = new int[9][9];

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

        for (int i = 0; i < 9; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < 9; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        backtracking(0, 0);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                sb.append(board[i][j]).append(" ");
            }
            sb.append("\n");
        }
        System.out.print(sb.toString());
    }

    private static boolean backtracking(int x, int y) {
        if (x == 9) {  // ํ•œ ์ค„ ๋๋‚˜๋ฉด ๋‹ค์Œ ์ค„๋กœ
            x = 0;
            y++;
            if (y == 9) return true;  // ๋ชจ๋“  ์นธ์„ ๋‹ค ์ฑ„์šด ๊ฒฝ์šฐ
        }

        if (board[y][x] != 0) {
            return backtracking(x + 1, y);  // ์ด๋ฏธ ์ฑ„์›Œ์ง„ ์นธ์ด๋ฉด ๋‹ค์Œ ์นธ์œผ๋กœ
        }

        for (int num = 1; num <= 9; num++) {
            if (isValid(y, x, num)) {
                board[y][x] = num;
                if (backtracking(x + 1, y)) return true;
                board[y][x] = 0;
            }
        }

        return false;
    }

    // ํ˜„์žฌ ์œ„์น˜์— num์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌ
    private static boolean isValid(int y, int x, int num) {
        // ๊ฐ™์€ ํ–‰
        for (int i = 0; i < 9; i++) {
            if (board[y][i] == num) return false;
        }

        // ๊ฐ™์€ ์—ด
        for (int i = 0; i < 9; i++) {
            if (board[i][x] == num) return false;
        }

        // ๊ฐ™์€ 3x3 ๋ฐ•์Šค
        int startY = (y / 3) * 3;
        int startX = (x / 3) * 3;
        for (int i = startY; i < startY + 3; i++) {
            for (int j = startX; j < startX + 3; j++) {
                if (board[i][j] == num) return false;
            }
        }

        return true;
    }
}

@g0rnn g0rnn merged commit cdd061c into main Jul 21, 2025
1 check passed
@g0rnn g0rnn deleted the 28-kokeunho branch July 21, 2025 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants