문제 풀이/백준
백준 - 스도쿠 (2239) [C++]
JJJaewon
2024. 5. 8. 16:09
반응형
이 문제는 백트래킹 문제이다.
시간 복잡도를 조금이라도 줄이려면 애초에 백트래킹 탐색을 할 때 사전식으로 앞서도록 탐색하게 만들면 된다.
어떤 좌표 (y, x)가 있을 때, 이를 3으로 나눴다가 3으로 곱하면 해당 칸의 시작 인덱스를 구할 수 있다. 이걸 이용하면 좀 더 쉽게 구현할 수 있다. 물론 이는 0부터 시작해서 8로 끝나는 인덱스를 이용할 때 활용 가능하다.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define SIZE 9
int board[SIZE][SIZE];
void input() {
for (int y = 0; y < SIZE; y++) {
for (int x = 0; x < SIZE; x++) {
char c;
cin >> c;
board[y][x] = c - '0';
}
}
}
pair<int, int> findStart(int y, int x) {
y /= 3;
x /= 3;
y *= 3;
x *= 3;
return { y, x };
}
pair<int, int> nextPos(int y, int x) {
x++;
if (x == SIZE) {
x = 0;
y++;
}
return { y, x };
}
vector<int> candidate(int y, int x) {
vector<bool> check(10, false);
for (int i = 0; i < SIZE; i++) {
int numberX = board[y][i];
int numberY = board[i][x];
check[numberX] = true;
check[numberY] = true;
}
pair<int, int> start = findStart(y, x);
for (int i = start.first; i < start.first + 3; i++) {
for (int j = start.second; j < start.second + 3; j++) {
int number = board[i][j];
check[number] = true;
}
}
vector<int> results;
for (int i = 1; i <= 9; i++) {
if (!check[i]) {
results.push_back(i);
}
}
return results;
}
void print() {
for (int y = 0; y < SIZE; y++) {
for (int x = 0; x < SIZE; x++) {
cout << board[y][x];
}
cout << '\n';
}
cout << '\n';
}
bool solve(int y, int x) {
if (y == SIZE) {
print();
return true;
}
if (board[y][x] != 0) {
pair<int, int> next = nextPos(y, x);
bool result = solve(next.first, next.second);
if (result) {
return true;
}
return false;
}
vector<int> cand = candidate(y, x);
for (int c : cand) {
board[y][x] = c;
pair<int, int> next = nextPos(y, x);
bool result = solve(next.first, next.second);
if (result) {
return true;
}
board[y][x] = 0;
}
return false;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
input();
solve(0, 0);
return 0;
}
반응형